哈夫曼树的构建(c语言描述)

哈夫曼树又称最优树,是一类带权路径长度最短的路。

哈夫曼树结构:

typedef struct Htree{
    int data;//数据域,也可以不要,我这里是用来存放下标
    int parent,lchild,rchild;//父亲下标,左右儿子下标
    int weight;//权重
}Htree;
typedef struct{
	Htree TData[MAXSIZE];//哈夫曼树 
	int size;//这是该树的大小,n*2 
}HFMtree;

 

思路:(我个人这里用到的是堆栈,思路仁者见仁,智者见智)

1.将权重的集合(数组或其他集合)进行排序。

2.一一入栈,栈顶保证存放的是权重最小的那两个结点。

3.进入循环,将栈顶最小权重的两个结点弹出,弹出之后权重相加得到新结点。

4.新结点入栈。

5.将堆栈排序,栈顶保证存放的是权重最小的那两个结点。

6.重复 3,4,5直到栈为空.

 

#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 1000
/*
哈夫曼树的构建 
*/
typedef struct Htree{
    int data;
    int parent,lchild,rchild;
    int weight;
}Htree;
typedef struct{
	Htree TData[MAXSIZE];//哈夫曼树 
	int size;//这是该树的大小,n*2 
}HFMtree;
typedef struct{
	Htree Array[MAXSIZE];
	int top;//堆栈头 
}Stack_Array;//顺序表堆栈 
void Qsort(int left,int right,int a[]){
	if(left>=right){//递归出口 
		return;
	}
	int temp=a[left];//做好标兵 
	int i=left,j=right;
	while(i<j){
		//从右边开始检查起 
		while(temp<a[j]&&j>i){
			j--;
		}
		if(temp>=a[j]&&j>i){
			int t=a[j];
			a[j]=a[i];
			a[i]=t;
			i++;
		}
		while(temp>a[i]&&j>i){
			i++;
		}
		if(temp<a[i]&&j>i){
			int t=a[i];
			a[i]=a[j];
			a[j]=t;
			j--;
		}
	}
	//出来的时候i=j
	a[j]=temp;//在这里左边比他小 右边比他大
	Qsort(left,i-1,a);
	Qsort(i+1,right,a); 
}
void PushStack_Array(Stack_Array *S,Htree value){
	//顺序堆栈入栈
	S->Array[++S->top]=value;
}
Htree PopStack_Array(Stack_Array *S){
	Htree x=S->Array[S->top];
	S->top--;
	return x;
}
int isEmpty(Stack_Array S){
	if(S.top<=-1)return 1;
	return 0;
}
void sortS(Stack_Array *S){
	//对堆栈进行从大到小排序 (权重)
	int i,j,len=S->top+1;
	for(i=1;i<len;i++){
		for(j=1;j<i;j++){
			if(S->Array[j].weight<S->Array[i].weight){
				Htree t=S->Array[j];
				S->Array[j]=S->Array[i];
				S->Array[i]=t;
			}
		}
	}
}
//创建哈夫曼树
void Create(int n,int weight[],HFMtree &HT){
	//n是结点数,weight是权重的数组
	 Qsort(0,n-1,weight);//对权重数组进行从小到大排序
	 int i,j;
	 HT.size=n*2;
	 Stack_Array S;
	 //初始化权重数组,加入哈夫曼数组
	 for(i=1;i<=n;i++){
	 	HT.TData[i].data=i;
	 	HT.TData[i].weight=weight[i-1];
	 	HT.TData[i].parent=HT.TData[i].lchild=HT.TData[i].rchild=0;//初始化为0 
	 }
	 for(i=n;i>=1;i--)PushStack_Array(&S,HT.TData[i]);//从大到小入栈
	 i=9;
	 //此时栈顶为最小的两个
	 while(!isEmpty(S)){//循环至堆栈为空 	 	
		 //先出栈两次,得到两个权值最小的结点 
		 Htree h1,h2,ht;
		 h1=PopStack_Array(&S);
		 h2=PopStack_Array(&S);
		 
		 ht.weight=h1.weight+h2.weight;
		 ht.lchild=h1.data;ht.rchild=h2.data;//设置左右儿子
		 ht.data=i;
		 HT.TData[i++]=ht;//放入哈夫曼树 
		 HT.TData[h1.data].parent=HT.TData[h2.data].parent=ht.data;//把原结点的父亲更新一下 
		 PushStack_Array(&S,ht);//将新结点入栈 
		 
		 sortS(&S);//对堆栈从大到小排序(栈顶最小) 
	 } 
}

int main(){
	int W[8]={5,29,7,8,14,23,3,11},i;
	HFMtree HT;	
	Create(8,W,HT);	

	for(i=1;i<16;i++){
		printf("下标是:%d 权值是:%d ,父亲是:%d 左儿子是:%d,右儿子是:%d \n",HT.TData[i].data,HT.TData[i].weight,HT.TData[i].parent,HT.TData[i].lchild,HT.TData[i].rchild);
	}
 	return 0;
}

 

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值