二叉树的应用,掌握哈夫曼树创建方法

哈夫曼树是特殊二叉树,又称最优二叉树。该树的所有叶子结点都有权值,从而构造出带权路径最短的二叉树。

  1. 路径长度:树中路径上分支数目。
  2. 叶子结点权值:为每一个叶子结点赋予的一个数值。(哈夫曼树中,分支结点不需要赋予权值。)
  3. 权值不给定时,字符串中,字符出现频率可设为权值,根权值最终等于叶子结点权值之和。(用于验证建立是否正确)。
  4. 树的带权路径长度:树中所有叶子结点的权值乘以该结点的路径长度之和。WPL=Wk*Lk (求和);
    k->n,Wk为第k个叶子结点的权值,Lk为从根结点到第k结点的路径长度。
  5.     总n个结点,n-1次合并后,只剩一结点。
    

问题

  • n同为叶子节点数,有性质3得总结点数N=n-1?

  • selectmin函数中,p1,p2未使用引用或指针导致运行错误。

  • 数组做形参时的接收格式错误编译失败。

  • creathfmt函数中,for循环i未从n起始,运行错误。

  • t[i].weight =t[p1].weight +t[p2].weight ,大意将 t[p2].weight 写成t[p2].rchild 导致结果持续错误。

  • hfnode(htnode t[],int i,int j) 中,if(t[j].parent !=-1){ i=j,hfnode(t,i,j);//递归 为什么是逗号????? }//递归 ,为什么是逗号?????不理解句意。

  • mannode(htnode t[],int n)中,printf("\n%i的编码为:",t[i].weight );%i的用途??

解决

  • 混肴二叉树性质3,性质3内容为任意一颗二叉树,叶子节点数n,度为二的节点数n2,那么n=n2+1.或者是度为二的结点数n2=n-1。此处求总的结点数2*n-1
  • p1,p2作用是记录下标,将最终下标带回使用,形参改变,要引起实参改变,所以要使用引用或者指针。
  • 数组做参数的接收格式:例一维数组 (int data[ ]);二维数组(int data[ ][n]),n为具体数。
  • creathfmt函数中,for循环i从n起始,因为新生成的结点依次从n后插入。
  • 逐步个对照代码检查错误然后更正,细心。
  • 递归处使用分号也没有问题。

由键盘输入各个字符的权值,编程构造哈夫曼树。

#include<stdio.h>//数组做形参时的结构
#define MAX 100
typedef struct{
	int weight;//结点权值
	int lchild,rchild,parent;//左右孩子结点在组数中的序号,双亲在数组中序号
	//parent域判断结点是否已加入要建立的哈夫曼树中,初始值为-1,
}htnode;
//全局变量int n;
//哈夫曼树初始化子函数
void inithfmt(htnode t[],int n){//树中所有结点都要初始化!!!!!
	int i;
	for(i=0;i<2*n-1;i++){//满二叉树中总结点数2*n-1 性质2???
		t[i].weight =0;
		t[i].lchild =-1;
		t[i].rchild =-1;
		t[i].parent =-1;
		}
}
//输入权值
void inputweight(htnode t[],int n){
	int w,i;
	for(i=0;i<n;i++){//叶子结点赋值 i是下标
		printf("输入%d个权值:",i+1);
		scanf("%d",&w);
		getchar();//接收回车键
		t[i].weight =w;
		
	}
}
//选择最小值两个
void selectmin(htnode t[],int i,int &p1,int &p2){
	long min1=88888,min2=88888;//预设两个值 使他大于可能出现的最大权值
	int j;
	for(j=0;j<=i;j++){//比较至所有的叶子结点 所以取等号!!!!!
		if(t[j].parent ==-1){//结点未使用则继续
			if(min1>t[j].weight ){
				min1=t[j].weight ;//权值比设定值小 改变设定值
				p1=j;//p1存下标 带回使用
			}
		}
	}
	for(j=0;j<=i;j++){
		if(t[j].parent ==-1){
			if(min2>t[j].weight &&j!=p1){//附加条件 与选择的第一个值(下标不同)
				min2=t[j].weight ;
				p2=j;//记录下标
			}
		}
	}
}
//构造哈夫曼树,有t[2*n-1]为其根结点
void creathfmt(htnode t[],int n){
	int i,p1,p2;
	inithfmt(t,n);
	inputweight(t,n);
	for(i=n;i<2*n-1;i++){//i从n开始,因为新值依次插入数组尾端
		selectmin(t,i-1,p1,p2);
		t[p1].parent =t[p2].parent =i;
		t[i].lchild =t[p1].weight;
		t[i].rchild =t[p2].weight;
		t[i].weight =t[p1].weight +t[p2].weight ;//大意 t[p2].weight 写成t[p2].rchild
		
		
	}
}
//输出向量状态表
void print(htnode t[],int n){
	int i;
	printf("\n哈夫曼树的各边显示\n");
	for(i=0;i<2*n-1;i++){
	
	
		while(t[i].lchild !=-1){
		
			printf("(%d,%d),(%d,%d)\n",t[i].weight ,t[i].lchild ,t[i].weight ,t[i].rchild );
		break;	
		}
}
}



//哈夫曼编码函数
void hfnode(htnode t[],int i,int j){
	j=t[i].parent ;
	if(t[j].rchild ==t[i].weight ){
		printf("1");
	}
	else{
		printf("0");
	}
	if(t[j].parent !=-1){
		i=j,hfnode(t,i,j);//递归   为什么是逗号?????
	}
}
//求哈夫曼编码
void mannode(htnode t[],int n){
	int i,j,a;
	printf("\n输入的权值对应的哈夫曼编码;");
	for(i=0;i<n;i++){
		j=0;
		a=i;
		printf("\n%i的编码为:",t[i].weight );
		hfnode(t,i,j);
		i=a;
	}
	
}
main(){
	int n;
	htnode t[MAX];
	printf("\n输入权值个数");//等价于叶子个数
	scanf("%d",&n);
	creathfmt(t,n);
	print(t,n);
	mannode(t,n);
	
	
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值