#ifndef HUFFMAN_H
#define HUFFMAN_H
#define MAXHEIGHT 50
// Define tree node
typedef struct node {
char symbol;
int freq;
struct node *left, *right;
} HNODE;
// Define heap which store codes
typedef struct minHeap {
int size;
int capacity;
HNODE **array;
} MHEAP;
// Function for creating a new node
HNODE *newNode(char symbol, int freq) {
HNODE *p = (HNODE *) malloc(sizeof(HNODE));
if (p == NULL) {
printf("Failure: memory allocation\n");
return NULL;
}
// Create node, if allocation is successful
p->left = p->right = NULL;
p->symbol = symbol;
p->freq = freq;
return p;
}
// Function for creating min heap of given capacity
MHEAP *createHeap(int capacity) {
MHEAP *h = (MHEAP *)malloc(sizeof(MHEAP));
h->size = 0;
h->capacity = capacity;
h->array = (HNODE **) malloc(h->capacity * sizeof(HNODE *));
return h;
}
// Swap the heap nodes for heapify operation
void swapHNODE(HNODE **a, HNODE **b) {
HNODE *t = *a;
*a = *b;
*b = t;
}
// Heapify operation
void heapify(MHEAP *h, int idx) {
int smallest = idx;
int left = 2 * idx + 1;
int right = 2 * idx + 2;
if (left < h->size && h->array[left]->freq < h->array[smallest]->freq)
smallest = left;
if (right < h->size && h->array[right]->freq < h->array[smallest]->freq)
smallest = right;
if (smallest != idx) {
swapHNODE(&h->array[smallest], &h->array[idx]);
heapify(h, smallest);
}
}
// Check if size if 1
int checkSizeOne(MHEAP *h) {
// Heap size 1 implies a leaf
return (h->size == 1);
}
// Extract min
HNODE *deleteMin(MHEAP *h) {
HNODE *p = h->array[0]; // Get minimum
// Copy last node to first node
h->array[0] = h->array[h->size - 1];
--h->size; // Reduce the heap size
heapify(h, 0); // Restore heap property
return p; // Return after deletion
}
// Insertion function
void insertHeap(MHEAP *h, HNODE *hNode) {
++h->size; // Increment heap size
int i = h->size - 1; // Index of the blank last element.
while (i && hNode->freq < h->array[(i - 1) / 2]->freq) {
// If new node's frequency < parent's frequency
// push the parent down to and climb up
h->array[i] = h->array[(i - 1) / 2];
i = (i - 1) / 2; // Climb up
}
// Correct positon of new node found
h->array[i] = hNode;
}
void buildHeap(MHEAP *h) {
int n = h->size - 1;
int i;
for (i = (n - 1) / 2; i >= 0; --i)
heapify(h, i);
}
int isLeaf(HNODE *root) {
return !(root->left) && !(root->right);
}
MHEAP *createAndBuildHeap(char symbol[], int freq[], int size) {
MHEAP *h = createHeap(size);
for (int i = 0; i < size; ++i)
h->array[i] = newNode(symbol[i], freq[i]);
h->size = size;
buildHeap(h);
return h;
}
HNODE *buildHuffmanTree(char symbol[], int freq[], int size) {
HNODE *left, *right, *top;
// Create heap of frequencies associated with symbols
MHEAP *h = createAndBuildHeap(symbol, freq, size);
while (!checkSizeOne(h)) {
// Get a pair of least frequency nodes
left = deleteMin(h);
right = deleteMin(h);
// Use '$' as meta symbol
top = newNode('$', left->freq + right->freq);
top->left = left;
top->right = right;
insertHeap(h, top); // Insert meta symbol
}
return deleteMin(h); // Returns last meta symbol
}
// Print the array
void printArray(int arr[], int n) {
int i;
for (i = 0; i < n; ++i)
printf("%d", arr[i]);
printf("\n");
}
// Print the codes
void printHCodes(HNODE *root, int arr[], int top) {
if (root->left) {
arr[top] = 0; // Add 0 for left branch
printHCodes(root->left, arr, top + 1);
}
if (root->right) {
arr[top] = 1; // Add 1 for right branch
printHCodes(root->right, arr, top + 1);
}
// If a leaf is reached print the code
if (isLeaf(root)) {
printf(" %c | ", root->symbol);
printArray(arr, top);
}
}
// Wrapper function for printing Huffman code
void HuffmanCodes(char symbol[], int freq[], int size) {
int arr[MAXHEIGHT];
int top = 0;
// Build Huffman tree for give symbol set and
// corresponding symbol frequencies
HNODE *root = buildHuffmanTree(symbol, freq, size);
printHCodes(root, arr, top);
}
#endif