Advertisement
enfiskutensykkel

Huffman coding

Aug 16th, 2018
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.68 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <string.h>
  5. #include <errno.h>
  6. #include <stdbool.h>
  7.  
  8.  
  9. struct HNode
  10. {
  11.     struct HNode*   prev;
  12.     struct HNode*   next;
  13.     struct HNode*   left;
  14.     struct HNode*   right;
  15.     struct HNode*   parent;
  16.     double          freq;
  17.     uint8_t         length;
  18.     uint8_t         symbol;
  19.     uint32_t        code;
  20. };
  21.  
  22.  
  23. static void list_insert(struct HNode* after, struct HNode* node)
  24. {
  25.     node->next = after->next;
  26.     node->prev = after;
  27.     after->next->prev = node;
  28.     after->next = node;
  29. }
  30.  
  31.  
  32. static void list_remove(struct HNode* node)
  33. {
  34.     if (node->prev != NULL)
  35.     {
  36.         node->prev->next = node->next;
  37.     }
  38.     if (node->next != NULL)
  39.     {
  40.         node->next->prev = node->prev;
  41.     }
  42.     node->prev = NULL;
  43.     node->next = NULL;
  44. }
  45.  
  46.  
  47. static bool list_empty(const struct HNode* head)
  48. {
  49.     return head->next == head;
  50. }
  51.  
  52.  
  53. static struct HNode* list_peek(const struct HNode* head)
  54. {
  55.     if (!list_empty(head))
  56.     {
  57.         return head->next;
  58.     }
  59.  
  60.     return NULL;
  61. }
  62.  
  63.  
  64. static void tree_insert(struct HNode* parent, struct HNode* x, struct HNode* y)
  65. {
  66.     list_remove(x);
  67.     list_remove(y);
  68.  
  69.     x->parent = parent;
  70.     y->parent = parent;
  71.  
  72.     parent->parent = NULL;
  73.     parent->left = x;
  74.     parent->right = y;
  75.     parent->freq = x->freq + y->freq;
  76. }
  77.  
  78.  
  79. static void tree_clear(struct HNode** node)
  80. {
  81.     struct HNode* root = *node;
  82.  
  83.     if (root != NULL)
  84.     {
  85.         tree_clear(&root->left);
  86.         tree_clear(&root->right);
  87.         free(root);
  88.     }
  89.  
  90.     *node = NULL;
  91. }
  92.  
  93.  
  94. static void list_clear(struct HNode* head)
  95. {
  96.     while (!list_empty(head))
  97.     {
  98.         struct HNode* node = list_peek(head);
  99.         list_remove(node);
  100.         tree_clear(&node);
  101.     }
  102. }
  103.  
  104.  
  105. static struct HNode* find_position(struct HNode* head, double freq)
  106. {
  107.     struct HNode* prev = head;
  108.     struct HNode* curr = head->next;
  109.  
  110.     while (curr != head)
  111.     {
  112.         if (curr->freq >= freq)
  113.         {
  114.             return prev;
  115.         }
  116.  
  117.         prev = curr;
  118.         curr = curr->next;
  119.     }
  120.  
  121.     return curr;
  122. }
  123.  
  124.  
  125. static void count_frequency(double* frequency, const void* data, size_t length)
  126. {
  127.     bool even = true;
  128.     const unsigned char* ptr = data;
  129.     const unsigned char* end = ptr + length;
  130.  
  131.     for (; ptr != end; ptr++)
  132.     {
  133.         ++frequency[*ptr];
  134.         even = !!even;
  135.     }
  136.  
  137.     if (!even)
  138.     {
  139.         for (int i = 0; i < 256; ++i)
  140.         {
  141.             if (frequency[i] == 0)
  142.             {
  143.                 frequency[i] += 1;
  144.                 break;
  145.             }
  146.         }
  147.     }
  148. }
  149.  
  150.  
  151. static void node_clear(struct HNode* node)
  152. {
  153.     node->next = node;
  154.     node->prev = node;
  155.     node->left = NULL;
  156.     node->right = NULL;
  157.     node->parent = NULL;
  158.     node->symbol = 0;
  159.     node->freq = 0;
  160.     node->length = 0;
  161.     node->code = 0;
  162. }
  163.  
  164.  
  165. static struct HNode* node_create()
  166. {
  167.     struct HNode* node = malloc(sizeof(struct HNode));
  168.     if (node == NULL)
  169.     {
  170.         return NULL;
  171.     }
  172.  
  173.     node_clear(node);
  174.     return node;
  175. }
  176.  
  177.  
  178. static void tree_build_codes(struct HNode* node, uint8_t length, uint32_t code)
  179. {
  180.     if (node->left == NULL)
  181.     {
  182.         node->length = length;
  183.         node->code = code;
  184.     }
  185.     else
  186.     {
  187.         tree_build_codes(node->left, length + 1, code);
  188.         tree_build_codes(node->right, length + 1, code | (1 << length));
  189.     }
  190. }
  191.  
  192.  
  193. static int frequency_tree(struct HNode** root, struct HNode** table, double* frequency)
  194. {
  195.     struct HNode unassigned;
  196.     node_clear(&unassigned);
  197.  
  198.     *root = NULL;
  199.  
  200.     for (int i = 0; i < 256; ++i)
  201.     {
  202.         table[i] = NULL;
  203.         if (frequency[i] > 0)
  204.         {
  205.             struct HNode* leaf = node_create();
  206.             if (leaf == NULL)
  207.             {
  208.                 list_clear(&unassigned);
  209.                 return errno;
  210.             }
  211.             leaf->symbol = i;
  212.             leaf->freq = frequency[i];
  213.             table[i] = leaf;
  214.  
  215.             struct HNode* after = find_position(&unassigned, leaf->freq);
  216.             list_insert(after, leaf);
  217.         }
  218.     }
  219.  
  220.     while (unassigned.next->next != &unassigned)
  221.     {
  222.         struct HNode* parent = node_create();
  223.         if (parent == NULL)
  224.         {
  225.             list_clear(&unassigned);
  226.             return errno;
  227.         }
  228.  
  229.         struct HNode* x = list_peek(&unassigned);
  230.         list_remove(x);
  231.  
  232.         struct HNode* y = list_peek(&unassigned);
  233.         list_remove(y);
  234.  
  235.         tree_insert(parent, x, y);
  236.  
  237.         struct HNode* after = find_position(&unassigned, parent->freq);
  238.         list_insert(after, parent);
  239.     }
  240.  
  241.     struct HNode* node = list_peek(&unassigned);
  242.     list_remove(node);
  243.  
  244.     tree_build_codes(node, 0, 0);
  245.  
  246.     *root = node;
  247.     return 0;
  248. }
  249.  
  250.  
  251. static void print_symbol(const struct HNode* node)
  252. {
  253.     int i;
  254.     fprintf(stderr, "%02x %3u: ", node->symbol, node->length);
  255.     for (i = 0; i < node->length; ++i)
  256.     {
  257.         char bit = !!(node->code & (1 << i)) + '0';
  258.         fprintf(stderr, "%c", bit);
  259.     }
  260.  
  261.     for (; i < 8; ++i)
  262.     {
  263.         fprintf(stderr, " ");
  264.     }
  265.  
  266.     //fprintf(stderr, " %8.0f\n", node->freq);
  267.     fprintf(stderr, "\n");
  268. }
  269.  
  270.  
  271. static void print_table(struct HNode** table)
  272. {
  273.     for (int i = 0; i < 256; ++i)
  274.     {
  275.         if (table[i] != NULL)
  276.         {
  277.             print_symbol(table[i]);
  278.         }
  279.     }
  280. }
  281.  
  282.  
  283. static size_t encode(struct HNode** table, const void* src, size_t len, void* dst)
  284. {
  285.     const unsigned char* input = src;
  286.     const unsigned char* end = src + len;
  287.     unsigned char* output = dst;
  288.  
  289.     int bit = 0;
  290.     unsigned char byte = 0;
  291.  
  292.     while (input != end)
  293.     {
  294.         const struct HNode* ptr = table[*input++];
  295.  
  296.         for (int i = 0; i < ptr->length; ++i)
  297.         {
  298.             byte <<= 1;
  299.             byte |= !!(ptr->code & (1 << i));
  300.  
  301.             if (++bit == 8)
  302.             {
  303.                 *output++ = byte;
  304.                 byte = 0;
  305.                 bit = 0;
  306.             }
  307.         }
  308.     }
  309.  
  310.     if (bit != 0)
  311.     {
  312.         byte <<= (8 - bit);
  313.         *output = byte;
  314.     }
  315.  
  316.     return (output - ((unsigned char*) dst)) * 8 + bit;
  317. }
  318.  
  319.  
  320. static size_t decode(const struct HNode* root, const void* src, size_t len, void* dst)
  321. {
  322.     const unsigned char* input = src;
  323.     unsigned char* output = dst;
  324.  
  325.     int bitmask = 0x80;
  326.     const struct HNode* ptr = root;
  327.  
  328.     for (size_t i = 0; i < len; ++i)
  329.     {
  330.         bool right = !!(*input & bitmask);
  331.         bitmask >>= 1;
  332.  
  333.         if (bitmask == 0)
  334.         {
  335.             bitmask = 0x80;
  336.             ++input;
  337.         }
  338.  
  339.         if (right)
  340.         {
  341.             ptr = ptr->right;
  342.         }
  343.         else
  344.         {
  345.             ptr = ptr->left;
  346.         }
  347.  
  348.         if (ptr->left == NULL)
  349.         {
  350.             *output++ = ptr->symbol;
  351.             ptr = root;
  352.         }
  353.     }
  354.  
  355.     return (output - ((unsigned char*) dst)) * 8;
  356. }
  357.  
  358.  
  359. int main(int argc, char** argv)
  360. {
  361.     const char* string = "XXXX og XXXXX gjør ting de ikke kan, som f.eks. å implementere Huffman-koding";
  362.     size_t n = strlen(string) + 1;
  363.  
  364.     double freqs[256];
  365.     for (int i = 0; i < 256; ++i)
  366.     {
  367.         freqs[i] = 0;
  368.     }
  369.  
  370.     count_frequency(freqs, string, n);
  371.  
  372.     struct HNode* root;
  373.     struct HNode* table[256];
  374.     frequency_tree(&root, table, freqs);
  375.  
  376.     print_table(table);
  377.     fprintf(stderr, "\n");
  378.  
  379.     char encoded[n];
  380.     size_t len = encode(table, string, n, encoded);
  381.  
  382.     char decoded[n];
  383.     len = decode(root, encoded, len, decoded);
  384.  
  385.     tree_clear(&root);
  386.  
  387.     fprintf(stderr, "%s\n", string);
  388.     fprintf(stderr, "%s\n", decoded);
  389.  
  390.     return 0;
  391. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement