diff options
| author | Magnus Auvinen <magnus.auvinen@gmail.com> | 2008-09-23 10:20:07 +0000 |
|---|---|---|
| committer | Magnus Auvinen <magnus.auvinen@gmail.com> | 2008-09-23 10:20:07 +0000 |
| commit | 0e0972c53862177d7be40aa462ce7a0389f64b9e (patch) | |
| tree | 8ede2272ba0e7a4cb6e86d4f124a66dd45e40592 | |
| parent | 6874cc5bfa50ae221ddb04b91178cb323ff4a6fa (diff) | |
| download | zcatch-0e0972c53862177d7be40aa462ce7a0389f64b9e.tar.gz zcatch-0e0972c53862177d7be40aa462ce7a0389f64b9e.zip | |
fixed deterministic sort in the huffman tree generation
| -rw-r--r-- | src/engine/e_huffman.c | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/src/engine/e_huffman.c b/src/engine/e_huffman.c index 8adbb1f7..43914010 100644 --- a/src/engine/e_huffman.c +++ b/src/engine/e_huffman.c @@ -1,4 +1,3 @@ -#include <stdlib.h> /* qsort */ #include <memory.h> /* memset */ #include "e_huffman.h" @@ -8,15 +7,6 @@ typedef struct HUFFMAN_CONSTRUCT_NODE int frequency; } HUFFMAN_CONSTRUCT_NODE; -static int sort_func(const void *a, const void *b) -{ - if((*(HUFFMAN_CONSTRUCT_NODE **)a)->frequency > (*(HUFFMAN_CONSTRUCT_NODE **)b)->frequency) - return -1; - if((*(HUFFMAN_CONSTRUCT_NODE **)a)->frequency < (*(HUFFMAN_CONSTRUCT_NODE **)b)->frequency) - return 1; - return 0; -} - static void huffman_setbits_r(HUFFMAN_STATE *huff, HUFFMAN_NODE *node, int bits, int depth) { if(node->leafs[1] != 0xffff) @@ -31,10 +21,32 @@ static void huffman_setbits_r(HUFFMAN_STATE *huff, HUFFMAN_NODE *node, int bits, } } +/* TODO: this should be something faster, but it's enough for now */ +void bubblesort(HUFFMAN_CONSTRUCT_NODE **list, int size) +{ + int i, changed = 1; + HUFFMAN_CONSTRUCT_NODE *temp; + + while(changed) + { + changed = 0; + for(i = 0; i < size-1; i++) + { + if(list[i]->frequency < list[i+1]->frequency) + { + temp = list[i]; + list[i] = list[i+1]; + list[i+1] = temp; + changed = 1; + } + } + } +} + static void huffman_construct_tree(HUFFMAN_STATE *huff, const unsigned *frequencies) { - HUFFMAN_CONSTRUCT_NODE nodes_left_storage[HUFFMAN_MAX_NODES]; - HUFFMAN_CONSTRUCT_NODE *nodes_left[HUFFMAN_MAX_NODES]; + HUFFMAN_CONSTRUCT_NODE nodes_left_storage[HUFFMAN_MAX_SYMBOLS]; + HUFFMAN_CONSTRUCT_NODE *nodes_left[HUFFMAN_MAX_SYMBOLS]; int num_nodes_left = HUFFMAN_MAX_SYMBOLS; int i; @@ -52,20 +64,22 @@ static void huffman_construct_tree(HUFFMAN_STATE *huff, const unsigned *frequenc nodes_left_storage[i].frequency = frequencies[i]; nodes_left_storage[i].node_id = i; nodes_left[i] = &nodes_left_storage[i]; - } + } huff->num_nodes = HUFFMAN_MAX_SYMBOLS; /* construct the table */ while(num_nodes_left > 1) { - qsort(nodes_left, num_nodes_left, sizeof(HUFFMAN_CONSTRUCT_NODE *), sort_func); + /* we can't rely on stdlib's qsort for this, it can generate different results on different implementations */ + bubblesort(nodes_left, num_nodes_left); huff->nodes[huff->num_nodes].num_bits = 0; huff->nodes[huff->num_nodes].leafs[0] = nodes_left[num_nodes_left-1]->node_id; huff->nodes[huff->num_nodes].leafs[1] = nodes_left[num_nodes_left-2]->node_id; nodes_left[num_nodes_left-2]->node_id = huff->num_nodes; nodes_left[num_nodes_left-2]->frequency = nodes_left[num_nodes_left-1]->frequency + nodes_left[num_nodes_left-2]->frequency; + huff->num_nodes++; num_nodes_left--; } |