哈夫曼樹權值計算
阿新 • • 發佈:2020-11-29
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 }