霍夫曼編碼是一種基於字元出現頻率的貪婪演算法,構建最優二元樹,讓高頻字元使用較短編碼,廣泛應用於資料壓縮(如 ZIP、JPEG、MP3)。本文示範以 C 語言在 VC++ 6.0 環境下實現完整的壓縮/解壓縮程式。
#define MAXCHAR 30000
#define MAXNODE 300
#define MAXNUM 150
typedef char InfoType;
struct HtNode {
long weight; // 權重(頻率)
char info; // 字元
int parentIndex; // 父節點索引
int llinkIndex; // 左子節點索引
int rlinkIndex; // 右子節點索引
};
struct HtTree {
struct HtNode ht[MAXNODE];
int rootIndex;
};
typedef struct HtTree* PHtTree;
採用陣列儲存樹節點,葉節點數 m,內部節點 m-1,總節點 2m-1。
m-1 次選取兩個最小權重且無父節點的節點合併。HaffCode codeList[128],索引即 ASCII 值,查找 O(1)。PHtTree haffmanAlgorithm(int m, long *w) {
PHtTree pht = malloc(sizeof(struct HtTree));
// 初始化葉節點
for (int i = 0; i < 2*m-1; ++i) {
pht->ht[i].llinkIndex = pht->ht[i].rlinkIndex = pht->ht[i].parentIndex = -1;
if (i < m) { pht->ht[i].weight = w[i]; pht->ht[i].info = (char)i; }
else pht->ht[i].weight = -1;
}
// 合併內部節點
for (int i = 0; i < m-1; ++i) {
// 找出兩個最小權重無父節點的節點
// ... 略 ...
pht->ht[first].parentIndex = m+i;
pht->ht[second].parentIndex = m+i;
pht->ht[m+i].weight = pht->ht[first].weight + pht->ht[second].weight;
pht->ht[m+i].llinkIndex = first;
pht->ht[m+i].rlinkIndex = second;
pht->rootIndex = m+i;
}
return pht;
}
typedef struct {
char asciiCode;
unsigned long haffCode;
int haffCodeLen;
} HaffCode;
HaffCode codeList[128];
// 遍歷樹填入 codeList,索引 = asciiCode
// 查找:sHaffCode = codeList[inChar].haffCode;
unsigned char。zlib (DEFLATE = LZ77 + 霍夫曼) 取代純霍夫曼以獲得更佳壓縮比。霍夫曼編碼雖非現代壓縮演算法的最先端,但其原理清晰、實作簡單,是理解無損壓縮核心思想的最佳切入點。完整原始碼可參考文章附件或自行依上述架構實作。