The following source codes are used in this chapter.
Huffman code
1. Main function using HuffmanTree class
// Data Structure & Algorithm C++, Otgonbayar Tovuudorj
// Chapter 18: File Compression and Decompression
// Huffman code
#include "pq.h"
#define nil (-1)
class HuffmanTree {
struct node { int L, RorCh; };
node *Htree;
int n, root;
public:
HuffmanTree(const unsigned long *freq);
~HuffmanTree() { delete []Htree; }
int NewNode(int L, int x) {
Htree[n].L = L; Htree[n++].RorCh = x;
return n - 1;
}
int getroot() { return root; }
friend void traverse(class HuffmanTree &, struct CodeTable *,
int, unsigned int code=0, int len=0);
};
struct item {
unsigned long freq;
int ptr;
item(){}
item(unsigned long f, int p): freq(f), ptr(p){}
int operator>(item &x){return freq < x.freq;}
};
HuffmanTree::HuffmanTree(const unsigned long *freq) {
Htree = new node[511];
n = 0;
PQ<item> pq(256); // Size of priority queue
for (int j=0; j<256; j++)
if (freq[j]) pq.insert(item(freq[j], NewNode(nil, j)));
item t1, t2;
if (pq.empty()) cout << "Empty input file." << endl;
else {
for (;;) {
t1 = pq.remove();
if (pq.empty()) break;
t2 = pq.remove();
pq.insert(item(t1.freq + t2.freq,
NewNode(t1.ptr, t2.ptr)));
}
root = t1.ptr;
}
}
struct CodeTable { unsigned code, len; }; // For code table
void traverse(HuffmanTree &Tr, CodeTable *t, int p,
unsigned code, int len) {
if (Tr.Htree[p].L == nil) {
unsigned char ch = Tr.Htree[p].RorCh;
t[ch].code = code;
t[ch].len = len;
cout <<"ch: " << ch << " code: " << code << " len:" << len << endl;
}
else {
code <<= 1; len++;
traverse(Tr, t, Tr.Htree[p].L, code, len);
traverse(Tr, t, Tr.Htree[p].RorCh, code | 1, len);
}
}
int main() {
cout << "Huffman code.\n";
unsigned long freq[256];
unsigned char ch;
int j, k, b;
char s[] = "AAABBBCCDEFGGGGGHHZZ"; // *s -> s[]
for (j=0; j<256; j++) freq[j] = 0;
j=0;
while (ch=s[j++]) freq[ch]++;
HuffmanTree Tr(freq);
CodeTable t[256]; // t is the code table
for (int i=0; i<256; i++) t[i].code = t[i].len = 0;
traverse(Tr, t, Tr.getroot());
}
2. Header file: pq.h
// Data Structure & Algorithm C++, Otgonbayar Tovuudorj
// Chapter 18: File Compression and Decompression
// Priority queue class
// File name: pq.h
#include <iostream>
using namespace std;
template <class Type>
class PQ {
Type *array;
int MaxSize, Nel, ChunkSize;
void adjustH();
public:
PQ(int size, int incr=10) {
MaxSize = size;
array = new Type[MaxSize];
Nel = 0; ChunkSize = incr;
}
~PQ() { delete[]array; }
void insert(Type item);
Type remove();
int empty() { return Nel == 0; }
};
template <class Type>
void PQ<Type>::insert(Type item) {
int i, j;
if (Nel == MaxSize) {
Type *aOld = array;
array = new Type[MaxSize += ChunkSize];
for (i=0; i<Nel; i++) array[i] = aOld[i];
delete[] aOld;
}
i = Nel++;
while (i > 0 && item > array[(i-1)/2]) {
array[i] = array[(i-1)/2]; i = (i-1)/2;
}
array[i] = item;
}
template <class Type>
Type PQ<Type>::remove() {
Type item = array[0];
array[0] = array[--Nel];
adjustH();
return item;
}
template <class Type>
void PQ<Type>::adjustH() {
int i = 0, j;
Type item = array[0];
while ((j = 2 * i + 1) < Nel) {
if (j < Nel - 1 && array[j+1] > array[j]) j++;
if (array[j]>item) {
array[i] = array[j]; i = j;
}
else break;
}
array[i] = item;
}
