哈夫曼树及其哈夫曼编码(数据结构C语言)

哈夫曼树及其哈夫曼编码

输入5种字符以及他们的权值:a:10, b:5, c:20, d:8,e:15
第一步:构建哈夫曼树
在这里插入图片描述
第二步:为哈夫曼树的每一条边编码(左0右1),图中没有标
在这里插入图片描述
代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define N 5			//带权值的叶子节点数
#define M 2*N-1		//n个叶子节点构造的哈夫曼树有2n-1个结点
#define MAX 10000
typedef char TElemType;

typedef struct{
	unsigned int weight;     //权值只能是正数
	unsigned int parent,lchild,rchild;
}HTNode;

typedef HTNode HuffmanTree[M+1];		//动态分配数组存储哈夫曼树,0号单元不适用
typedef char *HuffmanCode[N+1];			//动态分配数组存储哈夫曼编码



//在HT[1...k]里选择parent为0的且权值最小的2结点,其序号分别为s1,s2,
void Select(HuffmanTree HT,int k,int &s1,int &s2){
	
	unsigned int tmp = MAX ,temp = 0;
	for(int i=1;i<=k;i++){
		if(!HT[i].parent ){  //双亲为0
			//找出最小值
			if(tmp>HT[i].weight ){
				tmp = HT[i].weight ;     //tmp最后为最小的weight
				temp = i;
			}
		}
	}
	s1 = temp;
	tmp = MAX;
	temp = 0;
	for(int i = 1;i<=k;i++){
		if((!HT[i].parent )&& i!=s1){
			//找出第二个小值
			if(tmp > HT[i].weight ){
				tmp = HT[i].weight ;
				temp = i;
			}
		}
	}
	s2 = temp;
}

void CreateHuffmanCoding (HuffmanTree &HT,HuffmanCode &HC,int *w,int n){
	//存放n个字符的权值(均>0),构造哈夫曼树HT,并求出n个字符的哈夫曼树HC
	int i;
	if(n<=0)   //空树
		return ;
	//对树赋初值
	for(i = 1;i<=n;i++){    //将哈夫曼表的双亲,左右子树置0
		HT[i].weight = w[i];
		HT[i].lchild = 0;
		HT[i].parent = 0;
		HT[i].rchild = 0;

	}
	for(i = n+1;i<=M;i++){
		HT[i].weight = 0;
		HT[i].lchild = 0;
		HT[i].parent = 0;
		HT[i].rchild = 0;
	}
	//创建哈夫曼树
	for(i=n+1;i<=M;i++){
		int s1,s2;
		Select(HT,i-1,s1,s2);
		HT[s1].parent  = i;
		HT[s2].parent = i;
		HT[i].lchild = s1;
		HT[i].rchild = s2;
		HT[i].weight = HT[s1].weight + HT[s2].weight ;   //值i的权值
	}
	
	//为每个字符求解哈夫曼编码,从叶子到根逆向求解每个字符的哈夫曼编码
	char *ch = (char *)malloc (n*sizeof (char));
	ch[n-1]='\0';			//编码结束符
	int start ,c,f;
	for(int i = 1;i<=N;i++){     //逐个字符求哈夫曼编码
		start = N-1;			//编码结束的位置
		for(c=i,f=HT[i].parent ;f!=0;c=f,f=HT[f].parent ){     //从叶子到根 的逆向求编码
			if(HT[f].lchild == c){
				ch[--start] = '0';
			}else{
				ch[--start] = '1';
			}
			
		}
		//每次ch的后N-start个位置有编码存在
		HC[i]= (char *)malloc((N-start)*sizeof (char));
		//将ch的后N-start个元素赋值给H[i] 指向的字符串
		strcpy (HC[i],&ch[start]);
	}
	

} 
//打印哈夫曼树
void prinfHuffmanTree(HuffmanTree HT,char ch[]){
	printf("data\tweight\tparent\tlchild\trchild\n");
	for(int i = 1;i<=M;i++){
		if(i>N){
			printf(" -\t%d\t%d\t%d\t%d\n",HT [i].weight ,HT[i].parent ,HT[i].lchild ,HT[i].rchild );
		}else{
			printf(" %c\t%d\t%d\t%d\t%d\n",ch[i], HT [i].weight ,HT[i].parent ,HT[i].lchild ,HT[i].rchild );
		}

	}
}
//输出哈夫曼编码
void printHuffmanCoding(HuffmanCode HC,char ch[]){
	for(int i = 1; i<=N;i++){
		printf("%c:%s\n", ch[i],HC[i]);
	}
	printf("\n");
}

int main(){
	
	HuffmanTree HT;
	HuffmanCode HC;
	TElemType ch[N+1];
	int w[N+1];
	printf("\n********哈夫曼树及哈夫曼编码的存储表示:*********\n");
	printf("请输入%d 个字符以及字符对应的权值:\n",N);
	for(int i = 1;i<=N;i++){
		scanf("%c%d",&ch[i],&w[i]);
		getchar();		//去掉换行符
	}
	
	CreateHuffmanCoding (HT,HC,w,N);			//创建哈夫曼树
	printf("\n********哈夫曼树如下:*********\n");
	prinfHuffmanTree(HT,ch);
	printf("\n********哈夫曼编码:*********\n");
	printHuffmanCoding(HC,ch);

	return 0;
}

运行截图:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YJY@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值