C++優先佇列解決哈夫曼(Huffmam)編碼問題 (STL priority_queue)
阿新 • • 發佈:2019-01-22
Huffman樹和Huffman編碼的概念在此不再贅述了。
實現Huffman樹的難點在於如何從節點集合中找到兩個權最小的節點並將其合併。
STL中的priority_queue基於小頂堆實現,能滿足較快找到權重最小兩節點的要求。
1.priority_queue的基本用法
首先對priority_queue的基本用法做簡要介紹
#include <iostream> #include <queue> using namespace std; struct Node { int n; Node(int _n):n(_n){} }; //自定義比較類 struct cmp { bool operator() (const Node &a, const Node &b) { return a.n > b.n; } }; int main() { //宣告一個優先佇列pq priority_queue<Node, vector<Node>, cmp> pq; Node n1(9); Node n2(1); Node n3(5); Node n4(2); //將元素依次插入優先佇列pq pq.push(n1); pq.push(n2); pq.push(n3); pq.push(n4); //輸出隊首元素,輸出結果為1 cout << pq.top().n << endl; //取出隊首元素 pq.pop(); return 0; }
2.實現Huffman編碼
#include<iostream> #include<cstdio> #include<queue> #include<deque> using namespace std; //字元結構體 struct Hcode { char ch;//字元 deque<int> huffcode;//字元的哈夫曼編碼 }; //Huffman樹節點 struct Hnode { int weight = 0; Hnode *parent = NULL; Hnode *Lchild = NULL; Hnode *Rchild = NULL; }; struct cmp { bool operator() (const Hnode *a, const Hnode *b) { return a->weight > b->weight; } }; //Huffman樹建構函式 void huff_init(priority_queue<Hnode*, vector<Hnode*>, cmp>& pq, int n) { for(int i=0; i<n-1; i++) { if(pq.size() == 1) break; Hnode *Pnode = new Hnode(); Hnode *Lnode = pq.top(); pq.pop(); Hnode *Rnode = pq.top(); pq.pop(); Pnode->weight = Lnode->weight + Rnode->weight; Pnode->Lchild = Lnode; Pnode->Rchild = Rnode; Lnode->parent = Pnode; Rnode->parent = Pnode; pq.push(Pnode); } } //Huffman編碼獲取函式 /*獲取Huffman編碼的基本思想是從Huffman樹的葉子節點出發,自底向上 * 若當前結點為父節點的左子樹則在huffcode頭部插入編碼1,為左子樹 * 則在huffcode頭部插入編碼0(01順序不影響最優編碼長度),直到根 * 節點,Huffman編碼獲取完成,從huffcode中順序輸出即可*/ void huff_code(Hnode *node, Hcode *code, int n) { for(int i=0; i<n; i++) { Hnode *currNode = &node[i]; for(;;) { if(currNode->parent == NULL) break; else { if(currNode->parent->Rchild == currNode) { code[i].huffcode.push_front(1); } else { code[i].huffcode.push_front(0); } } currNode = currNode->parent; } } } //Huffman編碼輸出函式 void huff_print(Hcode *code, int n) { for(int i=0; i<n; i++) { printf("%c 's Huffman code is:",code[i].ch); deque<int>::iterator it; for(it = code[i].huffcode.begin(); it != code[i].huffcode.end(); it++) cout << *it; cout << endl; } } int main() { int n;//字元數 scanf("%d",&n); Hcode code[n]; Hnode node[n]; //依次讀入字元頻率 for(int i=0; i<n; i++) scanf("%d",&node[i].weight); fflush(stdin); //依次讀入字元 for(int i=0; i<n; i++) scanf("%c",&code[i].ch); //構造優先佇列並初始化 priority_queue<Hnode*, vector<Hnode*>, cmp> pq; for(int i=0; i<n; i++) pq.push(node+i); //構造Huffman樹 huff_init(pq, n); //獲得Huffman編碼 huff_code(node, code, n); //輸出Huffman編碼 huff_print(code, n); return 0; }
3.輸入輸出樣例
input: 645 13 12 16 9 5
ABCDEF
output: A 's Huffman code is:0
B 's Huffman code is:101
C 's Huffman code is:100
D 's Huffman code is:111
E 's Huffman code is:1101
F 's Huffman code is:1100