1 #include <iostream>
2 #include <iomanip>
3 using namespace std;
4
5 //哈夫曼树的存储表示
6 typedef struct
7 {
8 int weight; // 权值
9 int parent, lChild, rChild; // 双亲及左右孩子的下标
10 }HTNode, *HuffmanTree;
11
12
13 // 选择权值最小的两颗树
14 void SelectMin(HuffmanTree hT, int n, int &s1, int &s2)
15 {
16 s1 = s2 = 0;
17
18 int i;
19 for(i = 1; i < n; ++ i){
20 if(0 == hT[i].parent){
21 if(0 == s1){
22 s1 = i;
23 }
24 else{
25 s2 = i;
26 break;
27 }
28 }
29 }
30 if(hT[s1].weight > hT[s2].weight){
31 int t = s1;
32 s1 = s2;
33 s2 = t;
34 }
35
36 for(i += 1; i < n; ++ i){
37 if(0 == hT[i].parent){
38 if(hT[i].weight < hT[s1].weight){
39 s2 = s1;
40 s1 = i;
41 }else if(hT[i].weight < hT[s2].weight){
42 s2 = i;
43 }
44 }
45 }
46 }
47
48 // 构造有n个权值(叶子节点)的哈夫曼树
49 void CreateHufmanTree(HuffmanTree &hT)
50 {
51 int n, m;
52 cin >> n;
53 m = 2*n - 1;
54
55 hT = new HTNode[m + 1]; // 0号节点不使用
56 for(int i = 1; i <= m; ++ i){
57 hT[i].parent = hT[i].lChild = hT[i].rChild = 0;
58 }
59 for(int i = 1; i <= n; ++ i){
60 cin >> hT[i].weight; // 输入权值
61 }
62 hT[0].weight = m; // 用0号节点保存节点数量
63
64 /****** 初始化完毕, 创建哈夫曼树 ******/
65 for(int i = n + 1; i <= m; ++ i){
66 int s1, s2;
67 SelectMin(hT, i, s1, s2);
68
69 hT[s1].parent = hT[s2].parent = i;
70 hT[i].lChild = s1; hT[i].rChild = s2; // 作为新节点的孩子
71 hT[i].weight = hT[s1].weight + hT[s2].weight; // 新节点为左右孩子节点权值之和
72 }
73 }
74
75 int HuffmanTreeWPL_(HuffmanTree hT, int i, int deepth)
76 {
77 if(hT[i].lChild == 0 && hT[i].rChild == 0){
78 return hT[i].weight * deepth;
79 }
80 else{
81 return HuffmanTreeWPL_(hT, hT[i].lChild, deepth + 1) + HuffmanTreeWPL_(hT, hT[i].rChild, deepth + 1);
82 }
83 }
84
85 // 计算WPL(带权路径长度)
86 int HuffmanTreeWPL(HuffmanTree hT)
87 {
88 return HuffmanTreeWPL_(hT, hT[0].weight, 0);
89 }
90
91 // 销毁哈夫曼树
92 void DestoryHuffmanTree(HuffmanTree &hT)
93 {
94 delete[] hT;
95 hT = NULL;
96 }
97
98 int main()
99 {
100 HuffmanTree hT;
101 CreateHufmanTree(hT);
102 cout << "WPL = " << HuffmanTreeWPL(hT) << endl;
103 DestoryHuffmanTree(hT);
104 return 0;
105 }