-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhuffmanv2-legup.c
221 lines (185 loc) · 4.87 KB
/
huffmanv2-legup.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
/* OBS.: Resultados da codificação verificados no site:
* http://resources.nerdfirst.net/huffman
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 129
#define MAX_INT 2147483647
#define ALPHABET_SIZE 128
#define TEXT_SIZE 682
#define TRUE 1
#define FALSE 0
/* TRIE DEFINITIONS */
typedef struct node Node;
struct node {
unsigned long int freq;
char ch;
char code[50];
short int done;
Node *parent;
Node *left;
Node *right;
};
char texto[TEXT_SIZE] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent eget risus vitae massa semper aliquam quis mattis quam. Morbi vitae tortor tempus, placerat leo et, suscipit lectus. Phasellus ut euismod massa, eu eleifend ipsum. Nulla eu neque commodo, dapibus dolor eget, dictum arcu. In nec purus eu tellus consequat ultricies. Donec feugiat tempor turpis, rutrum sagittis mi venenatis at. Sed molestie lorem a blandit congue. Ut pellentesque odio quis leo volutpat, vitae vulputate felis condimentum. Praesent vulputate fermentum lorem, id rhoncus sem vehicula eu. Quisque ullamcorper, orci adipiscing auctor viverra, velit arcu malesuada metus, in volutpat tellus sem at justo.";
Node alfabeto[ALPHABET_SIZE];
// Esses nós servem como nós intermediarios da arvore, em contraposição às folhas da árvore
Node intermediarios[ALPHABET_SIZE];
int used_intermediaries;
int count_frequencies();
Node *build_trie();
/* MINIMUM PRIORITY QUEUE DEFINITIONS */
Node *heap[MAX];
int heap_size;
void init_heap();
void heapify();
Node *get_min();
void insert(Node *new);
void swap(int pos1, int pos2);
void generate_codes(Node *root);
int main(int argc, char const *argv[]) {
int i;
unsigned long int output_size = 0, input_size = 0;
Node *raiz, *aux;
char code[50], input;
printf("\nInicializando nós...\n");
for (int i = 0; i < ALPHABET_SIZE; i++) {
alfabeto[i].ch = i;
alfabeto[i].freq = 0;
alfabeto[i].done = FALSE;
alfabeto[i].parent = NULL;
alfabeto[i].left = NULL;
alfabeto[i].right = NULL;
}
printf("Inicialização OK\n");
printf("\nCalculando frequência de caracteres...\n");
input_size = count_frequencies();
printf("\n");
printf("Calculo de frequencia OK\n");
printf("\nBuildando trie...\n");
raiz = build_trie();
printf("Build OK\n");
printf("\nGerando códigos...\n");
generate_codes(raiz);
printf("Gerando códigos OK\n");
printf("\nFim do programa\n");
return 0;
}
/* TRIE IMPLEMENTATIONS */
// Conta a frequencia de cada caractere da string hardcoded
int count_frequencies() {
int i, input_size = 0;
char input;
while (scanf("%c", &input) != EOF) {
input_size++;
alfabeto[input].freq++;
}
for (int i = 0; i < ALPHABET_SIZE; i++) {
if (alfabeto[i].freq > 0)
insert(&alfabeto[i]);
}
return input_size;
}
// Constroi a trie de codificação. Retorna a raiz da trie.
Node *build_trie() {
Node *raiz;
while (heap_size > 1) {
raiz = &intermediarios[used_intermediaries];
raiz->left = get_min();
raiz->left->parent = raiz;
raiz->right = get_min();
raiz->right->parent = raiz;
raiz->freq = raiz->left->freq + raiz->right->freq;
insert(raiz);
used_intermediaries++;
}
raiz = get_min();
return raiz;
}
/* MINIMUM PRIORITY QUEUE IMPLEMENTATIONS */
void init_heap() {
int i;
for (i = 1; i < MAX+1; i++) {
heap[i] = NULL;
}
heap_size = 0;
}
void heapify() {
int pai, filho;
pai = 1;
filho = 2;
while (filho <= heap_size) {
if (filho < heap_size && heap[filho]->freq > heap[filho + 1]->freq)
filho++;
if (heap[filho]->freq < heap[pai]->freq)
swap(pai, filho);
else
break;
pai = filho;
filho = 2*filho;
}
}
Node *get_min() {
Node *result = heap[1];
heap[1] = heap[heap_size];
heap[heap_size] = NULL;
heap_size--;
heapify();
return result;
}
void insert(Node *new) {
int p;
if (heap_size == MAX) {
printf("Heap cheio\n");
return;
}
heap_size++;
heap[heap_size] = new;
p = heap_size;
while(p > 1 && heap[p/2]->freq > heap[p]->freq ) {
swap(p/2, p);
p = p/2;
}
}
void swap(int pos1, int pos2) {
Node *temp;
temp = heap[pos1];
heap[pos1] = heap[pos2];
heap[pos2] = temp;
}
void generate_codes(Node *root) {
Node *aux = root;
int index = 0;
char code[50];
while (!root->done) {
// se for uma folha
if (aux->left == NULL && aux->right == NULL) {
code[index] = '\0';
strcpy(aux->code, code);
//printf("%s -> '%c' (freq= %d) // %ld bits\n", aux->code, aux->ch, aux->freq, strlen(aux->code));
aux->done = TRUE;
aux = aux->parent;
index--;
}
// se for um nó interno e não teve suas duas subtries codificadas
// OBS.: começa sempre pelo filho esquerdo
else if (!aux->left->done || !aux->right->done ){
if(!aux->left->done) {
code[index] = '0';
index++;
aux = aux->left;
}
else {
code[index] = '1';
index++;
aux = aux->right;
}
}
// se for um nó interno e suas subtries foram inteiramente codificadas
else {
aux->done = TRUE;
aux = aux->parent;
index--;
}
}
}