Recent Posts
None | 16 sec ago
None | 46 sec ago
None | 49 sec ago
None | 1 min ago
None | 1 min ago
None | 1 min ago
None | 1 min ago
None | 2 min ago
None | 2 min ago
PHP | 2 min ago
Free Subdomains
Want a pastebin.com sub-domain for your community?
learn more...
What is pastebin?
Pastebin is a website that hosts all your text & code on dedicated servers for easy sharing.
learn more...
Learn a little bit about the new Pastebin.com on our help page. hide message
By Anonymous on the 9th of Feb 2010 07:51:28 PM Download | Raw | Embed | Report
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5.  
  6. #define NUM_CHARS 256
  7.  
  8. struct treenode {
  9.         int freq;
  10.         unsigned char ch;
  11.         treenode *left, *right;
  12. };
  13.  
  14. typedef struct _pq {
  15.         int heap_size;
  16.         treenode *A[NUM_CHARS];
  17. } PQ;
  18.  
  19. void create_pq (PQ *p) {
  20.         p->heap_size = 0;
  21. }
  22.  
  23. int parent (int i) {
  24.         return (i-1) / 2;
  25. }
  26.  
  27. int left (int i) {
  28.         return i * 2 + 1;
  29. }
  30.  
  31. int right (int i) {
  32.         return i * 2 + 2;
  33. }
  34.  
  35. void heapify (PQ *p, int i) {
  36.         int l, r, min;
  37.         treenode *t;
  38.  
  39.         l = left (i);
  40.         r = right (i);
  41.  
  42.         if (l < p->heap_size && p->A[l]->freq < p->A[i]->freq)
  43.         min = l;
  44.         else
  45.         min = i;
  46.         if (r < p->heap_size && p->A[r]->freq < p->A[min]->freq)
  47.         min = r;
  48.  
  49.         if (min != i) {
  50.                 t = p->A[i];
  51.                 p->A[i] = p->A[min];
  52.                 p->A[min] = t;
  53.                 heapify (p, min);
  54.         }
  55. }
  56.  
  57. void insert_pq (PQ *p, treenode *r) {
  58.         int i;
  59.  
  60.         p->heap_size++;
  61.         i = p->heap_size - 1;
  62.  
  63.         while ((i > 0) && (p->A[parent(i)]->freq > r->freq)) {
  64.                 p->A[i] = p->A[parent(i)];
  65.                 i = parent (i);
  66.         }
  67.         p->A[i] = r;
  68. }
  69.  
  70. treenode *extract_min_pq (PQ *p) {
  71.         treenode *r;
  72.  
  73.         if (p->heap_size == 0) {
  74.                 printf ("heap underflow!\n");
  75.                 exit (1);
  76.         }
  77.         r = p->A[0];
  78.         p->A[0] = p->A[p->heap_size-1];
  79.         p->heap_size--;
  80.         heapify (p, 0);
  81.         return r;
  82. }
  83.  
  84. unsigned int get_frequencies (FILE *f, unsigned int v[]) {
  85.         int r, n;
  86.  
  87.         for (n=0;;n++) {
  88.  
  89.                 r = fgetc (f);
  90.  
  91.                 if (feof (f)) break;
  92.  
  93.                 v[r]++;
  94.         }
  95.         return n;
  96. }
  97.  
  98. treenode *build_huffman (unsigned int freqs[]) {
  99.         int i, n;
  100.         treenode *x, *y, *z;
  101.         PQ p;
  102.  
  103.         create_pq (&p);
  104.  
  105.         for (i=0; i< NUM_CHARS; i++) {
  106.                 x = new treenode;
  107.                 x->left = NULL;
  108.                 x->right = NULL;
  109.                 x->freq = freqs[i];
  110.                 x->ch = (char) i;
  111.                 insert_pq (&p, x);
  112.         }
  113.  
  114.         n = p.heap_size-1;
  115.         for (i=0; i< n; i++) {
  116.         z = new treenode;
  117.                 x = extract_min_pq (&p);
  118.                 y = extract_min_pq (&p);
  119.                 z->left = x;
  120.                 z->right = y;
  121.                 z->freq = x->freq + y->freq;
  122.                 insert_pq (&p, z);
  123.         }
  124.         return extract_min_pq (&p);
  125. }
  126.  
  127. void traverse (treenode *r, int level, char code_so_far[], char *codes[]) {
  128.  
  129.         if ((r->left == NULL) && (r->right == NULL)) {
  130.                 code_so_far[level] = 0;
  131.                 codes[r->ch] = strdup (code_so_far);
  132.         } else {
  133.                 code_so_far[level] = '0';
  134.                 traverse (r->left, level+1, code_so_far, codes);
  135.                 code_so_far[level] = '1';
  136.                 traverse (r->right, level+1, code_so_far, codes);
  137.         }
  138. }
  139.  
  140. int nbits, current_byte, nbytes;
  141.  
  142. void bitout (FILE *f, char b) {
  143.  
  144.         current_byte <<  1;
  145.  
  146.         if (b == '1') current_byte |= 1;
  147.  
  148.         nbits++;
  149.  
  150.         if (nbits == 8) {
  151.                 fputc (current_byte, f);
  152.                 nbytes++;
  153.                 nbits = 0;
  154.                 current_byte = 0;
  155.         }
  156. }
  157.  
  158. void encode_file (FILE *infile, FILE *outfile, char *codes[]) {
  159.         unsigned char ch;
  160.         char *s;
  161.         current_byte = 0;
  162.         nbits = 0;
  163.         nbytes = 0;
  164.  
  165.         for (;;) {
  166.  
  167.                 ch = fgetc (infile);
  168.                 if (feof (infile)) break;
  169.  
  170.                 for (s=codes[ch]; *s; s++) bitout (outfile, *s);
  171.         }
  172.  
  173.         while (nbits) bitout (outfile, '0');
  174. }
  175.  
  176.  
  177. int main (int argc, char *argv[]) {
  178.         FILE *f, *g;
  179.         treenode *r;
  180.         unsigned int n, freqs[NUM_CHARS];
  181.         char *codes[NUM_CHARS], code[NUM_CHARS], fname[100];
  182.  
  183.         if (argc != 2) {
  184.                 fprintf (stderr, "%s <fisier>\n", argv[0]);
  185.                 exit (1);
  186.         }
  187.  
  188.         memset (freqs, 0, sizeof (freqs));
  189.  
  190.         f = fopen (argv[1], "r");
  191.         if (!f) {
  192.                 perror (argv[1]);
  193.                 exit (1);
  194.         }
  195.  
  196.         n = get_frequencies (f, freqs);
  197.         fclose (f);
  198.  
  199.         r = build_huffman (freqs);
  200.  
  201.         traverse (r, 0, code, codes);
  202.  
  203.         sprintf (fname, "%s.huf", argv[1]);
  204.         g = fopen (fname, "w");
  205.         if (!g) {
  206.                 perror (fname);
  207.                 exit (1);
  208.         }
  209.  
  210.         fwrite (freqs, NUM_CHARS, sizeof (int), g);
  211.  
  212.         fwrite (&n, 1, sizeof (int), g);
  213.  
  214.         f = fopen (argv[1], "r");
  215.         if (!f) {
  216.                 perror (argv[1]);
  217.                 exit (1);
  218.         }
  219.  
  220.         encode_file (f, g, codes);
  221.         fclose (f);
  222.         fclose (g);
  223.         printf ("%s is %0.2f%% of %s\n",
  224.         fname, (float) nbytes / (float) n, argv[1]);
  225.         exit (0);
  226. }
Submit a correction or amendment below. Make A New Post
To highlight particular lines, prefix each line with @h@
Syntax highlighting:
Post expiration:
Post exposure:
Name / Title:
Email: