9
9
*/
10
10
11
11
#include "huffman.h"
12
+ #include "compare.h"
12
13
#include "def.h"
14
+ #include "hash.h"
15
+ #include "hash_table.h"
13
16
14
- static inline int huffman_node_compare (HuffmanNode * node1 ,
15
- HuffmanNode * node2 )
17
+ static inline int huffman_node_compare (HuffmanNode * node1 , HuffmanNode * node2 )
16
18
{
17
- if (node1 -> weight > node2 -> weight ) {
19
+ if (node1 -> weight < node2 -> weight ) {
18
20
return -1 ;
19
21
} else if (node1 -> weight > node2 -> weight ) {
20
22
return 1 ;
@@ -57,7 +59,7 @@ static inline HuffmanNode *huffman_heap_pop(Heap *heap)
57
59
HuffmanTree * huffman_tree_new (Heap * heap )
58
60
{
59
61
HuffmanTree * tree = (HuffmanTree * )malloc (sizeof (HuffmanTree ));
60
-
62
+
61
63
HuffmanNode * node1 = NULL ;
62
64
HuffmanNode * node2 = NULL ;
63
65
@@ -71,6 +73,7 @@ HuffmanTree *huffman_tree_new(Heap *heap)
71
73
72
74
unsigned int weight = node1 -> weight + node2 -> weight ;
73
75
HuffmanNode * node = huffman_node_new ('\0' , weight );
76
+ heap_insert (heap , node );
74
77
75
78
if (node1 -> weight < node2 -> weight ) {
76
79
node -> left = node1 ;
@@ -102,3 +105,87 @@ void huffman_tree_free(HuffmanTree *tree)
102
105
huffman_tree_postorder_free (tree -> root );
103
106
free (tree );
104
107
}
108
+
109
+ static inline huffman_node_is_leave (HuffmanNode * node )
110
+ {
111
+ return node -> left == NULL && node -> right == NULL ;
112
+ }
113
+
114
+ static void huffman_tree_postorder_to_hash_table (HuffmanNode * node ,
115
+ HashTable * hash_table ,
116
+ BitMap * bitmap )
117
+ {
118
+ if (node == NULL ) {
119
+ return ;
120
+ }
121
+
122
+ if (node -> left != NULL ) {
123
+ BitMap * left_bitmap = bitmap_clone (bitmap );
124
+ bitmap_append (left_bitmap , 0 );
125
+ huffman_tree_postorder_to_hash_table (
126
+ node -> left , hash_table , left_bitmap );
127
+ }
128
+
129
+ if (node -> right != NULL ) {
130
+ BitMap * right_bitmap = bitmap_clone (bitmap );
131
+ bitmap_append (right_bitmap , 1 );
132
+ huffman_tree_postorder_to_hash_table (
133
+ node -> right , hash_table , right_bitmap );
134
+ }
135
+
136
+ if (huffman_node_is_leave (node )) {
137
+ // todo: char_dup is not valid here.!!!
138
+ char * ch = (char * )malloc (sizeof (char ));
139
+ * ch = node -> value ;
140
+ hash_table_insert (hash_table , ch , bitmap );
141
+ } else {
142
+ bitmap_free (bitmap );
143
+ }
144
+ }
145
+
146
+ static HashTable * huffman_tree_to_hash_table (HuffmanTree * tree )
147
+ {
148
+ /** key: char, value: bitmap */
149
+ HashTable * hash_table =
150
+ hash_table_new (hash_char , char_equal , free , bitmap_free );
151
+ HuffmanNode * node = tree -> root ;
152
+ BitMap * bitmap = bitmap_new (0 );
153
+ huffman_tree_postorder_to_hash_table (tree -> root , hash_table , bitmap );
154
+ return hash_table ;
155
+ }
156
+
157
+ BitMap * huffman_encode (HuffmanTree * tree , Text * text )
158
+ {
159
+ /** key: char, value: bitmap */
160
+ HashTable * hash_table = huffman_tree_to_hash_table (tree );
161
+ BitMap * bitmap = bitmap_new (0 );
162
+
163
+ for (unsigned int i = 0 ; i < text_length (text ); ++ i ) {
164
+ char ch = text_char_at (text , i );
165
+ BitMap * bits = (BitMap * )hash_table_get (hash_table , & ch );
166
+ for (unsigned int j = 0 ; j < bits -> num_bits ; ++ j ) {
167
+ bitmap_append (bitmap , bitmap_get (bits , j ));
168
+ }
169
+ }
170
+ hash_table_free (hash_table );
171
+ return bitmap ;
172
+ }
173
+
174
+ Text * huffman_decode (HuffmanTree * tree , BitMap * code )
175
+ {
176
+ Text * text = text_new ();
177
+ HuffmanNode * node = tree -> root ;
178
+ for (unsigned int i = 0 ; i < code -> num_bits ; ++ i ) {
179
+ if (bitmap_get (code , i )) {
180
+ node = node -> right ;
181
+ } else {
182
+ node = node -> left ;
183
+ }
184
+
185
+ if (huffman_node_is_leave (node )) {
186
+ text_append (text , node -> value );
187
+ node = tree -> root ;
188
+ }
189
+ }
190
+ return text ;
191
+ }
0 commit comments