问题的由来:
有一组带权节点组成的森林,每个棵树都只有一个节点,其权值是被访问的概率.
那么将这个森林合并为一颗二叉树,如何使根节点到这些节点的路径最短(优)?
这样的树也叫判定树或选择树,而Huffman树是是判定树的最优实现.
Huffman 树实现原理
在森林中每次取两个权值最小的节点,用这两个节点的权值相加得到一个新节点,
并成为其的左右子节点.构成一个新的二叉树.重复上述步骤,直到只剩一棵树.
这颗树就是Huffman 树了.
代码实现:
//tree node
typedef struct treeLink{
float data;
struct treeLink *Lchild, *parent, *Rchild;
struct treeLink *next;
struct treeLink *last;
}treeLink;
//构建Huffman tree
treeLink *getHT(float data[],int length){
int i;
//树的节点
treeLink *min1, *min2, *head, *sumNode;
//双链表头结点
linkedList *link = newDLink();
//将节点添加到双链表中
for(i=0;i<length;i++){
//添加初始节点
addFirst(link,newNode(data[i]));
}
//构架Huffman树
//当只剩一个节点时停止循环
while(link->length > 1){
min1 = findMin(link);//找到一个最小的节点
Remove(link,min1);//将这个小节点移除链表(不删除(free))
min2 = findMin(link);
Remove(link,min2);
//用两个最小节点权值之和构建一个新节点
sumNode = newNode(min1->data + min2->data);
//两个最小节点成为新节点的左右child
sumNode->Lchild = min1;
sumNode->Rchild = min2;
//新节点加入链表参与组合
addFirst(link,sumNode);
}
return link->head->next;
}
//test
void testH(){
int length = 5;
float arr[] = {0.05, 0.2, 0.25, 0.15, 0.35};
treeLink *root;
root = getHT(arr,length);
printH(root);//打印到控制台
}