數據結構之Huffman樹的C++實現

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樹有不少應用,壓縮與解壓縮就與它有關。

 。

相關文章
相關標籤/搜索