147 lines
2.7 KiB
C
147 lines
2.7 KiB
C
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#define MAX 10000
|
||
|
|
||
|
typedef struct treeNode {
|
||
|
char val;
|
||
|
int freq;
|
||
|
struct treeNode *left, *right;
|
||
|
} treeNode;
|
||
|
|
||
|
typedef struct heap {
|
||
|
int size;
|
||
|
treeNode **arr;
|
||
|
} heap;
|
||
|
|
||
|
heap *newHeap() {
|
||
|
heap *h = malloc(sizeof(heap));
|
||
|
h->size = 0;
|
||
|
h->arr = malloc(sizeof(treeNode *) * MAX);
|
||
|
|
||
|
return h;
|
||
|
}
|
||
|
|
||
|
int parent(int i) { return (i - 1) / 2; }
|
||
|
|
||
|
int left(int i) { return i * 2 + 1; }
|
||
|
|
||
|
int right(int i) { return i * 2 + 2; }
|
||
|
|
||
|
void swapNode(treeNode **l, treeNode **r) {
|
||
|
treeNode *tmp = *l;
|
||
|
*l = *r;
|
||
|
*r = tmp;
|
||
|
}
|
||
|
|
||
|
void insert(heap *h, treeNode *val) {
|
||
|
int i = h->size++;
|
||
|
|
||
|
h->arr[i] = val;
|
||
|
|
||
|
while (h->arr[i]->freq < h->arr[parent(i)]->freq) {
|
||
|
swapNode(&h->arr[i], &h->arr[parent(i)]);
|
||
|
i = parent(i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void heapify(heap *h, int i) {
|
||
|
// from up to down.
|
||
|
int smallest = i;
|
||
|
int l = left(i), r = right(i);
|
||
|
// Check for OOB!!!!!!
|
||
|
if (l < h->size && h->arr[smallest]->freq > h->arr[l]->freq) {
|
||
|
smallest = l;
|
||
|
}
|
||
|
if (r < h->size && h->arr[smallest]->freq > h->arr[r]->freq) {
|
||
|
smallest = r;
|
||
|
}
|
||
|
|
||
|
if (smallest != i) {
|
||
|
swapNode(&h->arr[i], &h->arr[smallest]);
|
||
|
heapify(h, smallest);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
treeNode *extractMin(heap *h) {
|
||
|
treeNode *res = h->arr[0];
|
||
|
// printf("Poped: %c %d\n", res->val, res->freq);
|
||
|
h->arr[0] = h->arr[h->size - 1];
|
||
|
h->size--;
|
||
|
|
||
|
heapify(h, 0);
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
treeNode *newNode(char val, int freq) {
|
||
|
treeNode *n = malloc(sizeof(treeNode));
|
||
|
|
||
|
n->freq = freq;
|
||
|
n->val = val;
|
||
|
n->left = n->right = NULL;
|
||
|
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
treeNode *buildHuffmanTree(heap *h) {
|
||
|
while (h->size != 1) {
|
||
|
treeNode *l = extractMin(h);
|
||
|
treeNode *r = extractMin(h);
|
||
|
|
||
|
treeNode *new = newNode('#', l->freq + r->freq);
|
||
|
new->left = l;
|
||
|
new->right = r;
|
||
|
|
||
|
insert(h, new);
|
||
|
}
|
||
|
|
||
|
return extractMin(h);
|
||
|
}
|
||
|
|
||
|
int isLeaf(treeNode *tr) { return (!tr->left) && (!tr->right); }
|
||
|
|
||
|
void printCode(treeNode *tr, char *input) {
|
||
|
treeNode *ptr;
|
||
|
int top = 0;
|
||
|
while (input[top] != '\n' && input[top] != '\0') {
|
||
|
ptr = tr;
|
||
|
while (!isLeaf(ptr)) {
|
||
|
if (input[top] == '0') {
|
||
|
// printf("%c", input[top]);
|
||
|
ptr = ptr->left;
|
||
|
top++;
|
||
|
} else if (input[top] == '1') {
|
||
|
// printf("%c", input[top]);
|
||
|
ptr = ptr->right;
|
||
|
top++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// printf(":%c\n", ptr->val);
|
||
|
printf("%c", ptr->val);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void printTree(treeNode *tr) {}
|
||
|
|
||
|
int main(void) {
|
||
|
heap *h = newHeap();
|
||
|
insert(h, newNode('a', 7));
|
||
|
insert(h, newNode('b', 19));
|
||
|
insert(h, newNode('c', 2));
|
||
|
insert(h, newNode('d', 6));
|
||
|
insert(h, newNode('e', 32));
|
||
|
insert(h, newNode('f', 3));
|
||
|
insert(h, newNode('g', 21));
|
||
|
insert(h, newNode('h', 10));
|
||
|
|
||
|
treeNode *huffmanTree = buildHuffmanTree(h);
|
||
|
|
||
|
char input[MAX];
|
||
|
fgets(input, MAX, stdin);
|
||
|
|
||
|
printCode(huffmanTree, input);
|
||
|
|
||
|
return 0;
|
||
|
}
|