最優二叉樹算法
練習做一下構造最優二叉樹的算法,不過如何計算WPL呢?
本次未能實現,希望懂的人可以幫我解決一下這個問題,不勝感激!
// // 頭文件:HuffmanTree.h // // 葉子結點的最大數量 #define LEAVES_COUNT 4 // // 二叉樹的最大結點總數 #define NODES_COUNT (2 * LEAVES_COUNT - 1) // // 哈夫曼樹的結點結構體 typedef struct tagHuffmanTreeNode { float weight; // 權值,假設權值都是大於零的值 int parent; // 指示雙親 int lchild; // 指示左孩子 int rchild; // 指示右孩子 }HuffmanNode; // // 哈夫曼樹定義為二維數組 typedef HuffmanNode HuffmanTree[NODES_COUNT]; // // 構造一棵哈夫曼樹 void CreateHuffmanTree(HuffmanTree tree); // // 初始化 void InitHuffmanTree(HuffmanTree tree); // // 輸入葉子的權值 void InputWeightsOfLeaves(HuffmanTree tree); // // 選擇兩個權最小的結點生成新的結點 void SelectMin(HuffmanTree tree, int maxValue, int *left, int *right); // // 計算哈夫曼樹的最小帶權路徑長度之和 int ComputeWPL(HuffmanTree tree);
// // 測試哈夫曼樹的構造,譯碼 // HuffmanTree.c #include <stdio.h> #include <stdlib.h> #include "HuffmanTree.h" int main() { HuffmanTree tree; // 構造哈夫曼樹 CreateHuffmanTree(tree); printf("WPL=%d\n", ComputeWPL(tree)); return 0; } // // 構造一棵哈夫曼樹 void CreateHuffmanTree(HuffmanTree tree) { int i; int left, right; InitHuffmanTree(tree); // 初始化 printf("輸入%d個結點值:\n", LEAVES_COUNT); InputWeightsOfLeaves(tree); // 輸入葉子權值至T[0..n-1]的weight域 // 共進行n-1次合並,新結點依次存於T[i]中 for (i = LEAVES_COUNT; i < NODES_COUNT; i++) { // 在tree中0~i-1中選擇最小的兩個根結點 SelectMin(tree, i - 1, &left, &right); // 在i個結點作為新合成結點的雙親 tree[left].parent = i; tree[right].parent = i; tree[i].lchild = left; // 最小權的根結點是新結點的左孩子 tree[i].rchild = right; // 次小權的根結點是新結點的右孩子 // 新結點的權值 tree[i].weight = tree[left].weight + tree[right].weight; } } // // 初始化 // 因為C語言數組的下界為0,故用-1表示空指針。樹中某結點的lchild、rchild和parent不等於-1時, // 它們分別是該結點的左、右孩子和雙親結點在向量中的下標。這裏設置parent域有兩個作用:其一是使查找 // 某結點的雙親變得簡單;其二是可通過判定parent的值是否為-1來區分根與非根結點。 // 將T[0..m-1]中2n-1個結點裏的三個指針均置為空(即置為-1),權值置為0。 void InitHuffmanTree(HuffmanTree tree) { int i = 0; for (i = 0; i < NODES_COUNT; i++) { tree[i].lchild = -1; tree[i].rchild = -1; tree[i].parent = -1; tree[i].weight = 0; } } // // 輸入葉子的權值 // 讀人n個葉子的權值存於向量的前n個分量(即T[0..n-1])中。它們是初始森林中n個孤立的根結點上的權值。 void InputWeightsOfLeaves(HuffmanTree tree) { char ch; int i; for (i = 0; i < LEAVES_COUNT; i++) { scanf("%c", &tree[i].weight); } } // // 選擇兩個權最小的結點生成新的結點 void SelectMin(HuffmanTree tree, int maxValue, int *left, int *right) { int i, j; int const MAX_VALUE = 10000; int m1, m2; for (i = 0; i < maxValue; i++) { m1 = m2 = MAX_VALUE; *left = 0; *right = 0; for (j = 0; j < LEAVES_COUNT + 1; j++) { if (tree[j].weight < m1 && tree[i].parent == -1) // 要求此結點還沒有構造 { m2 = m1; // 較大者給m2 *right = *left; m1 = tree[j].weight; // 取較小者 *left = j; } else if (tree[j].weight < m2 && tree[i].parent == -1) { m2 = tree[j].weight; *right = j; } } } } // // 計算哈夫曼樹的最小帶權路徑長度之和 int ComputeWPL(HuffmanTree tree) { int i = 0; int wpl = 0; for (i = 0; i < NODES_COUNT; i++) { if (IsLeaf(tree[i])) { wpl += tree[i].weight * (i + 1); // 這裏不正確,該如何獲取結點所有的層數呢? } } return wpl; } // // 判斷是否為葉子結點 int IsLeaf(HuffmanNode node) { return node.lchild == -1 && node.rchild == -1; }
最後更新:2017-04-03 18:51:56