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 }