赫夫曼树又称最优树,是一类带权路径长度最短的树。
路径:由一结点到另一结点间的分支所构成
路径长度:路径上的分支数目 例如上面的a->e的路径长度=2
带权路径长度:结点到根的路径长度与结点上权的乘积
树的带权路径长度:结点到根的路径长度与结点上权的乘积
赫夫曼树:带权路径长度最小的树
上面这个图的树的值为WPL=7*2+5*2+2*2+4*2=36
赫夫曼树构造过程
基本思想:使权大的结点靠近根
操作要点:对权值的合并、删除、替换,总是合并当前值最小的两个
赫夫曼树的构造过程
- 根据给定的n个权值{w1,w2,w3,….wn},构造n棵只有根结点的二叉树。
- 在森林中选取两棵根结点权值最小的树作左右子树,构造一棵新的二叉树,置新二叉树根结点权值为其左右子树根结点权值之和。
- 在森林中删除这两颗树,同时将新得到的二叉树加入森林中。
- 重复上述两步,直到只含一棵树为止,这棵树即赫夫曼树。
//--------赫夫曼树的存储表示------
typedef struct{
int weight;
int parent,lchild,rchild;
}HTNode, *HuffmanTree;
赫尔曼构造算法的实现
初始化HT[1…2n-1]:lch=rch=parent=0
输入初始n个叶子结点:置HT[1…n]的weight值
进行以下n-1次合并,依次产生HT[i],i=n+1…2n-1:
3.1.在HT[1…i-1]中选两个未被选过的weight最小的两个结点HT[s1]和HTs2
3.2)修改HT[s1]和HT[s2]的parent值:parent=i
3.3)置HT[i]:weight=HT[s1].weight+HT[s2].weight,lch=s1,rch=s2void CreatHuffmanTree(HuffmanTree &HT,int n) { //构造赫夫曼树HT if(n<=1)return; m=2*n-1; HT=new HTNode[m+1];//0号单元未用,所以需要动态分配m+1个单元,HT[m]表示根结点 for(i=1;i<=m;++i)//将1~m号单元中的双亲、左孩子,右孩子的下标都初始化为0 { HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0; } for(i=1;i<=n;++i)//输入前n个单元叶子结点的权值 { cin>>HT[i].weight; } for(i=1;i<m;++i) //通过n-1次·选择、删除、合并来创建赫夫曼树 { Select(HT,i-1,s1,s2); //在HT[k](1≤k≤i-1)中选择两个其双亲域为0且权值为最小的结点 //并返回它们在HT中序号s1和s2 HT[s1].parent=i; HT[s2].parent=i; //得到新结点i,从森林中删除是s1s2的双亲域有0改为i HT[i].lchild=s1;//s1,s2分别作为i的左右孩子 HT[i].rchild=s2; HT[i].weight=HT[s1].weight+HT[s2].weight; } }