101 lines
2.8 KiB
C

#include "lib/vec.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct HuffCode {
char byte;
char *code;
int frequency;
} HuffCode;
bool huffcode_cmp(HuffCode *first, HuffCode *second) {
int lendiff = strlen(first->code) - strlen(second->code);
if (lendiff == 0) {
int first_code = strtol(first->code, NULL, 2);
int second_code = strtol(second->code, NULL, 2);
return first_code >= second_code;
} else if (lendiff > 0) {
return true;
} else {
return false;
}
}
DECL_VEC(HuffVec, HuffCode *);
typedef struct MinHeap {
HuffVec *arr;
} MinHeap;
int minheap_parent(int i) { return (i - 1) / 2; }
int minheap_left_child(int i) { return (2 * i + 1); }
int minheap_right_child(int i) { return (2 * i + 2); }
HuffCode *minheap_get_min(MinHeap *heap) { return heap->arr->data[0]; }
MinHeap *minheap_new(HuffVec *arr) {
MinHeap *minheap = (MinHeap *)malloc(sizeof(MinHeap));
minheap->arr = arr;
return minheap;
}
void minheap_swap(MinHeap *heap, int idx, int jdx) {
HuffCode *temp = heap->arr->data[idx];
heap->arr->data[idx] = heap->arr->data[jdx];
heap->arr->data[jdx] = temp;
}
void *minheap_insert(MinHeap **_heap, HuffCode *value) {
MinHeap *heap = (*_heap);
int curr = heap->arr->elem_count - 1;
HuffVec_push(heap->arr, value);
while (curr > 0 && huffcode_cmp(heap->arr->data[minheap_parent(curr)],
heap->arr->data[curr])) {
minheap_swap(heap, minheap_parent(curr), curr);
curr = minheap_parent(curr);
}
return heap;
}
void minheap_print(MinHeap *heap) {
for (int i = 0; i < heap->arr->elem_count; i++) {
HuffCode *huffcode = heap->arr->data[i];
printf("%c: %s\n", huffcode->byte, huffcode->code);
}
}
int main() {
printf("Price Hiller, zfp106 (Spring 2024)\n");
printf("==================================\n");
HuffVec arr = HuffVec_new(2);
MinHeap *heap = minheap_new(&arr);
char chars[] = {'a', 'b', 'c', 'd', 'e'};
char *codes[] = {"100", "101", "00", "01", "11"};
int frequencies[] = {5, 9, 12, 13, 16};
printf("Huffman Encoding (Variable Bit)\n");
printf("Char | Freq\n");
HuffCode huffs[sizeof(frequencies) / sizeof(frequencies[0])] = {};
// Two for loops like this to maintain ownership over the huffman codes
for (int i = 0; i < sizeof(frequencies) / sizeof(frequencies[0]); i++) {
HuffCode huff = {
.byte = chars[i], .code = codes[i], .frequency = frequencies[i]};
huffs[i] = huff;
printf("%c | %d\n", huff.byte, huff.frequency);
}
printf("----------\n");
for (int i = 0; i < sizeof(frequencies) / sizeof(frequencies[0]); i++) {
heap = minheap_insert(&heap, &huffs[i]);
}
minheap_print(heap);
return 0;
}