哈夫曼樹(最優二叉樹)是帶權路徑長度最小的二叉樹,廣泛應用於無損數據壓縮。核心思想:
高頻字符編碼短,低頻字符編碼長,實現平均編碼長度最小化。
templatestruct mydata { mydata() {} mydata(int i) : freq(i) {} string coded; // 編碼結果 int freq; // 頻率 T data; // 字符數據 bool operator<(const mydata& rhs) { return freq < rhs.freq; } mydata operator+(mydata& rhs) { return mydata(freq + rhs.freq); } // 僅頻率相加 }; template class TreeNode { public: TreeNode() : pfather(NULL), plchild(NULL), prchild(NULL) {} T data; TreeNode *pfather, *plchild, *prchild; bool operator<(const TreeNode& rhs) { return data < rhs.data; } };
使用最小優先隊列(STL priority_queue):
templateTreeNode * MakeHuffmanTree(T* begin, T* end) { priority_queue *, vector *>, cmp > pri_que; TreeNode * pf = NULL; // 初始化葉子節點 for (T* iter = begin; iter != end; ++iter) { TreeNode * pNode = new TreeNode (); pNode->data = *iter; pNode->pfather = pf; pri_que.push(pNode); } // 合併構建 while (pri_que.size() > 1) { TreeNode * plchild = pri_que.top(); pri_que.pop(); TreeNode * prchild = pri_que.top(); pri_que.pop(); TreeNode * pNode = new TreeNode (); pNode->plchild = plchild; pNode->prchild = prchild; pNode->data = plchild->data + prchild->data; // 頻率相加 pri_que.push(pNode); } return pri_que.top(); }
深度優先搜索記錄路徑:左分支 '0',右分支 '1'
const int MAXLEN = 20;
char path[MAXLEN] = {0};
template
void DFS(T* root, int deep = -1, char a = '-') {
if (!root) return;
if (a != '-') path[deep] = a;
if (!root->plchild || !root->prchild) // 葉子節點
(root->data).coded = string(path, path + deep + 1);
if (root->plchild) DFS(root->plchild, deep + 1, '0');
if (root->prchild) DFS(root->prchild, deep + 1, '1');
}
廣度優先搜索收集葉子節點編碼:
templatevoid BFS(T* root, mydata* data) { queue que; que.push(root); while (!que.empty()) { T* pT = que.front(); que.pop(); if (pT->plchild) que.push(pT->plchild); if (pT->prchild) que.push(pT->prchild); if (!pT->plchild || !pT->prchild) { // 葉子節點 mydata* pd = data; while ((pT->data).data != pd->data) ++pd; pd->coded = (pT->data).coded; } } }
templateclass Huffman { public: void Coded(string& coded); // 編碼 void DeCode(const string& codedstr, string& decodestr); // 解碼 void InputData(T* begin, T* end); // 輸入數據並統計頻率 private: string FindVal(char c); void m_CalcFreq(T* begin, T* end); TreeNode >* root; mydata * data; int data_size; T* m_begin, *m_end; };
int main() {
char* pmystr = "cbcddddbbbbaaaaaaa";
Huffman h;
h.InputData(pmystr, pmystr + 18);
cout << "originstr: " << pmystr << endl;
string coded;
h.Coded(coded);
cout << "coded: " << coded << endl;
string decode;
h.DeCode(coded, decode);
cout << "decode: " << decode << endl;
return 0;
}
包含 TreeNode、cmp、mydata、MakeHuffmanTree、DFS、BFS、Huffman 類及 main 測試函數,可直接在 VS2012+ 編譯運行。
本文從原理到工程實現完整展示了哈夫曼編解碼,採用 STL 優先隊列與模板設計,代碼可復用性強,適合嵌入式壓縮、網絡傳輸等場景。