对哈夫曼树的一点预习与理解

Posted 纯纯的心儿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对哈夫曼树的一点预习与理解相关的知识,希望对你有一定的参考价值。

        赫夫曼(Huffman)树又称最优树,是一类带权路径长度最短的树,有着广泛的应用。

1基本概念

① 结点路径:从中一个结点到另一个结点的之间的分支构成这两个结点之间的路径。

② 路径长度:结点路径上的分支数目称为路径长度。

③ 树的路径长度:从树根到每一个结点的路径长度之和

    例图6-23的树。A到F :结点路径AEF;路径长度(即边的数目)  2;树的路径长度:3´1+5´2+2´3=19

结点的带权路径长度:从该结点的到树的根结点之间的路径长度与结点的权()的乘积

():各种开销代价频度等的抽象称呼。

树的带权路径长度:树中所有叶子结点的带权路径长度之和,记做:

        WPL=w1´l1+w2´l2+⋯+wn´ln=∑wi´li   (i=1,2,⋯,n)

其中:n为叶子结点的个数;wi为第i个结点的权值;li为第i个结点的路径长度。

 Huffman:具有n个叶子结点(每个结点的权值为wi) 的二叉树不止一棵,但在所有的这些二叉树中,

必定存在一棵WPL值最小的树,称这棵树为Huffman树(或称最优树)


 2. Huffman树的构造

①  根据n个权值w1,w2, ?,wn,构造成n棵二叉树的集合F=T1, T2,?,Tn,

其中每棵二叉树只有一个权值为wi的根结点,没有左、右子树;

②  在F中选取两棵根结点权值最小的树作为左、右子树构造一棵新的二叉树,且新的二叉树根结点权值为其左、

右子树根结点的权值之和;
③  在F中删除这两棵树,同时将新得到的树加入F中;
④  重复②、③,直到F只含一颗树为止。
    构造Huffman树时,为了规范,规定F=T1,T2, ?,Tn中权值小的二叉树作为新构造的二叉树的左子树,

权值大的二叉树作为新构造的二叉树的右子树;在取值相等时,深度小的二叉树作为新构造的二叉树的左子树,

深度大的二叉树作为新构造的二叉树的右子树。    


      图6-25是权值集合W=8, 3, 4, 6, 5, 5构造Huffman树的过程。所构造的Huffman树的WPL是: 
WPL=62+33+43+82+53+53 =79




附一个 建树的代码:

#define max_node 200
typedef struct

	unsigned int weight;
	unsigned int parent,lchild,rchild;
		
HTnode;


//生成树

void jianshu(unsigned n,HTnode ht[],unsigned m)

	unsigned int w;
	int j,k;
	for(k=1;k<m;k++)
	
		if(k<=n)
		
			cout<<"输入权值"<<endl; 
			cin>>w;
			ht[k].weight=w;
		
		else ht[k].weight=0; //分叶子节点 
		ht[k].parent=ht[k].lchild=ht[k].rchild;
	
	for(k=n+1;k<m;k++)
	
		unsigned w1=34234,w2=w1;
		int p1=0,p2=0;
		for(j=1;j<=k-1;j++)
		
			if(ht[j].parent==0)
			
				if(ht[j].weight<w1)
				
					w2=w1;
					p2=p1;
					w1=ht[j].weight;
					p1=j;
				
				else if(ht[j].weight<w2)
				
					w2=ht[j].weight;
					p2=j;
				
			
		
		ht[k].lchild=p1;
		ht[k].rchild=p2;
		ht[p1].parent=k;
		ht[k].weight=w1+w2;
		ht[p2].weight=k;
	
 



以上是关于对哈夫曼树的一点预习与理解的主要内容,如果未能解决你的问题,请参考以下文章

哈夫曼(Huffman)树及其应用

哈夫曼树

哈夫曼树

哈夫曼编码--贪心策略

什么是霍夫曼编码

第八篇