-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhuff.c
239 lines (199 loc) · 5.03 KB
/
huff.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "huff.h"
/* PROGRAM LAYOUT
* Open file, store contents in string
* Count number of occurences of each character by traversing string
* Use character count array to build tree
* Perform preorder traversal of tree, store traversal codes (0 - left, 1 - right)
* Write header to file
* Traverse string, match corresponding character to traversal codes
* Shift + write corresponding bits to file
* Calculate amount of time taken to perform tasks
*/
int main(int argc, char * argv[]) {
if (argc != 2) {
fprintf(stderr, "Invalid input");
return EXIT_FAILURE;
}
/* Create two arrays
* 1.) stores binary tree sequence
* 2.) stores count of each character
* */
char ascii[ASCIISIZE];
int asciiCount[ASCIISIZE];
for (int i = 0; i < ASCIISIZE; ascii[i] = '\0', asciiCount[i++] = 0);
/* Read and store file contents to string */
char * file_str = getString(argv[1]);
if (file_str == NULL){
fprintf(stderr, "Unable to read input file");
return EXIT_FAILURE;
}
//printf("%s\n", file_str);
for (int j = 0; file_str[j] != '\0'; asciiCount[(int) file_str[j++]]++);
Tree * huffTree = readTree(ascii);
if (!huffTree){
fprintf(stderr, "Unable to build Huffman binary tree");
}
/*
// Write to array for preorder binary tree traversal
getPreorder(&ascii, tree);
// Name + open .huff file
// For each element of array, shift bits to byte, write to .huff file
unsigned char writeByte = 0x0;
for (int k = 0; file_str[k] != '\0'; k++){
// shift bits into byte
fwrite
}
fclose
*/
destroyTree(huffTree);
free(file_str);
return EXIT_SUCCESS;
}
char * mergeStrings (const char * str1, const char * str2) {
return NULL;
}
/* Perform preorder traversal on tree, store codes in array
void getPreorder(char * ascii[], Tree * tree){
char * str1, str2;
}
*/
/* Read and store file contents to string */
char * getString(char * Filename) {
FILE * fptr = fopen(Filename, "r");
if (fptr == NULL) {
return NULL;
}
fseek(fptr, 0, SEEK_END);
int length = ftell(fptr);
fseek(fptr, 0, SEEK_SET);
char * inputStr = malloc(sizeof(*inputStr) * length);
if (inputStr) {
fread(inputStr, 1, length, fptr);
}
fclose(fptr);
return inputStr;
}
/* Builds forest of trees, then builds single binary tree*/
Tree * readTree(char ascii[]){
// Create linked list
Node * list = NULL;
for (int i = 0; i < ASCIISIZE; i++) {
if (ascii[i]){
// Create + add node to list in correct location
list = addToList(list, buildList(NULL, buildTree(i, ascii[i], NULL, NULL)));
}
}
// build binary tree from list
return popTree(buildTreeFromList(list));
// return NULL;
}
/*
* Build binary tree given linked list (forest of trees)
* Find two smallest nodes, combine and push to front of list
*/
List * buildTreeFromList(Node * list) {
// while list has more than one node
while (list->next != NULL) {
Tree * min1 = getMinimumNode(Node * list);
Tree * min2 = getMinimumNode(Node * list);
list = addToList(buildList(NULL, buildTree('\0', min1->count + min2->count, min1, min2)));
}
return list;
}
List * getMinimumNode(Node * list) {
while (list->next != NULL) {
list = list->next;
}
return popList(list);
}
/* Pushes new node to correct location in list */
List * addToList(Node * list, Node * newNode){
Node * prev = list, head = list;
if (head == NULL){
return head;
}
while (true) {
// If node is larger
if (newNode->ptr->count > list->ptr->count) {
break;
}
else if (newNode->ptr->count < list->ptr->count) {
if (list->next != NULL) {
prev = list;
list = list->next;
}
else {
break;
}
}
else if (newNode->ptr->count == list->ptr->count) {
if (newNode->ptr->label < list->ptr->label) {
break;
}
else if (list->next != NULL) {
prev = list;
list = list->next;
}
}
}
pushNode(prev, newNode);
return head;
}
/* Push node into linked list */
void pushNode(Node * pos, Node * newNode) {
newNode->next = pos->next;
pos->next = newNode;
}
/* Pop node from linked list */
List * popList(Node * node) {
List * temp = node;
node = node->next;
temp->next = NULL;
return temp;
}
/* Remove tree associated with list node */
Tree * popTree(Node * node) {
Tree * tmp = node->ptr;
node->ptr = NULL;
destroyList(node);
return tmp;
}
/* Build linked list node */
Node * buildList(Node * next, Tree * ptr){
Node * list = malloc(sizeof(*list));
list->next = next;
list->ptr = ptr;
return list;
}
/* Build binary tree node */
Tree * buildTree(char label, int count, Tree * left, Tree * right){
Tree * tree = malloc(sizeof(*tree));
tree->label = label;
tree->count = count;
tree->left = left;
tree->right = right;
return tree;
}
/* Release all memory associated with list */
void destroyList(Node * list){
Node * temp;
while (list != NULL) {
temp = list;
list = list->next;
destroyTree(list->ptr);
free(temp);
}
}
/* Release all memory associated with tree */
void destroyTree(Tree * tree){
if (tree == NULL){
return;
}
destroyTree(tree->left);
destroyTree(tree->right);
free(tree);
}