1、HUffman樹百度百科的定義以下:ios
給定N個權值做爲N個葉子結點,構造一棵二叉樹,若該樹的帶權路徑長度達到最小,稱這樣的二叉樹爲最優二叉樹,也稱爲哈夫曼樹(Huffman Tree)。哈夫曼樹是帶權路徑長度最短的樹,權值較大的結點離根較近。函數
2、Huffman樹的構造方法:測試
一、在N個節點組成的節點集合中選取兩個權值最小的節點組成一棵樹,新樹的根節點的權值爲兩個節點權值之和。spa
二、在節點集合中刪除這兩個節點。code
三、將根節點加入節點集合blog
四、重複以上過程直到節點集合中只剩一個節點隊列
節點集合{1,2,3,4,5}get
在節點集合中刪除最小的兩個節點,加入新的節點it
構造完成後的Huffman樹
io
3、Huffman樹的C++實現
由上面的過程看一個Huffman樹上的節點定義能夠以下:
權值(weight)、父節點位置(parent)、左右兒子節點位置(lchild、rchild)
1 #include<iostream> 2 #include<queue> 3 #include<vector> 4 using namespace std; 5 struct Huffman { 6 int weight;//權值 7 int lchild, rchild;//左、右孩子 8 int parent;//父節點 9 10 //這個構造函數是由於最開始每一個節點都是單獨的樹,兒子節點父節點均不存在 11 //方便初始化 12 Huffman(int w){ 13 weight = w; 14 lchild = -1; 15 rchild = -1; 16 parent = -1; 17 } 18 Huffman(int w,int l,int r,int p) { 19 weight = w; 20 lchild = l; 21 rchild = r; 22 parent = p; 23 } 24 25 };
咱們能夠用vector定義一個節點集合,叫作Huffman表
1 vector<Huffman> arg;//Huffman表 2 //構造Huffman樹並返回Huffman樹頭位置 3 int Huffman_head() { 4 int n = (int)arg.size();//元素計數器 5 while (n!=1) { 6 int min_1 = -1; 7 int min_2 = -1; 8 //在節點集合中找到最小的元素 9 for (int min_k = 0; min_k < (int)arg.size(); min_k++) { 10 if (arg.at(min_k).parent != -1) 11 continue; 12 if (min_1 == -1) 13 min_1 = min_k; 14 if (arg.at(min_k).weight < arg.at(min_1).weight) 15 min_1 = min_k; 16 } 17 arg.at(min_1).parent = (int)arg.size(); 18 //在節點集合中找到第二小的元素 19 for (int min_k = 0; min_k < (int)arg.size(); min_k++) { 20 if (arg.at(min_k).parent != -1) 21 continue; 22 if (min_2 == -1) 23 min_2 = min_k; 24 if (arg.at(min_k).weight < arg.at(min_2).weight) 25 min_2 = min_k; 26 } 27 arg.at(min_2).parent = (int)arg.size() ; 28 Huffman x (arg.at(min_1).weight + arg.at(min_2).weight, min_1, min_2, -1); 29 arg.push_back(x);//加入新節點 30 n--; 31 32 } 33 34 return (int)arg.size() - 1;//最後的節點必定是最末尾的值 35 36 }
利用隊列打印Huffman表
1 void print(int head) { 2 queue<int> pr; 3 cout<<"Num\t" << "weight\t" << "lchlid\t" << "rchild\t" << "parent\t" << endl; 4 pr.push(head); 5 while (!pr.empty()) { 6 int x = pr.front(); 7 if(arg.at(x).lchild != -1) 8 pr.push(arg.at(x).lchild); 9 if(arg.at(x).rchild != -1) 10 pr.push(arg.at(x).rchild); 11 cout << x << "\t" << arg.at(x).weight << "\t" << arg.at(x).lchild << "\t" << arg.at(x).rchild << "\t" << arg.at(x).parent << "\t" << endl; 12 pr.pop(); 13 } 14 15 16 }
測試代碼
int main() { arg = { {1},{2},{3},{4},{5} }; int p = Huffman_head(); print(p); return 0; }
結果以下
這只是Huffman樹最簡單的構造方法之一,Huffman樹有不少應用,壓縮與解壓縮就與它有關。
。