哈夫曼编码

样例输入(自己设的测试值):
7
40 30 15 5 4 3 3
A B C D E F G

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

/*哈夫曼结点数据结构*/
typedef struct Node{
	int weight;
	int Lch,Rch,Parent;
}HTNode,*HuffmanTree;

Select(HuffmanTree H,int N,int *p1,int *p2)
{
	int i,i_;
	int P[2*N-1];//创建一个新的数组用来找出H中最小的两个权重值 
	/*将H中的权重值全部赋给P*/ 
	for(i = 1;i <= 2*N-1;i++){
		P[i-1] = H[i].weight;
	}

	int t;//定义一个最小值用于冒泡排序法 
	for(i = 0;i < 2*N-1;i++){
		for(int i_ = i+1;i_ < 2*N-1;i_++){
			if(P[i] == 0&&P[i_] != 0){
				t = P[i];
				P[i] = P[i_];
				P[i_] = t;
			}else if(P[i] >= P[i_]&&P[i_] != 0){
				t = P[i];
				P[i] = P[i_];
				P[i_] = t;				
			}
		}
	}

	for(i = 1;i < 2*N-1;i++){
		if(H[i].weight == P[0])
			break;
	}
	*p2 = i;
	for(i_ = 1;i_ < 2*N-1;i_++){
		if(H[i_].weight == P[1]&&i_ != i)
			break;
	}
	*p1 = i_;
}
Code(HuffmanTree T,int root,int N,int i)
{
	int i_ = i;
	if(T[T[i].Parent].weight != root){
		i = T[i].Parent;
		Code(T,root,N,i);
	}
	
	if(T[T[i_].Parent].Lch == i_){
		printf("0");		
	}else{
		printf("1");
	}
}
int main()
{
	int N;//叶结点数目
	scanf("%d",&N);
	int i,p1,p2;
	
	/*申请一个大小为2*N的结构体数组空间(且闲置第一块数组空间)*/
	HuffmanTree H;
	H = (HTNode*)malloc(sizeof(HTNode)*2*N);
	H[0].Lch = H[0].Parent = H[0].Rch = H[0].weight = 0;

	/*对前N个叶子结点进行权重赋值且后N-1个结点全部置零*/
	for(i = 1;i <= 2*N-1;i++){
		if(i <= N){
			H[i].Lch = H[i].Parent = H[i].Rch = 0;
			scanf("%d",&H[i].weight);
		}else{
			H[i].Lch = H[i].Parent = H[i].Rch = H[i].weight = 0;
		}
	}
	/*开始制哈夫曼表*/
	HTNode T[2*N];
	for(int i_ = 1;i_ <= 2*N-1;i_++){
		T[i_].weight = H[i_].weight;
		T[i_].Lch = H[i_].Lch;
		T[i_].Rch = H[i_].Rch;
		T[i_].Parent = H[i_].Parent;
	};//T用来储存哈夫曼表
	for(int i_ = 1;i_ <= N-1;i_++){
		Select(H,N,&p1,&p2);
		/*改变双亲和左右孩子的值,制表*/
		T[N+i_].weight = H[p1].weight+H[p2].weight;
		if(H[p1].weight == H[p2].weight){
			T[N+i_].Lch = p1;T[N+i_].Rch = p2;T[p1].Parent = T[p2].Parent = N+i_;
		}else{
			T[N+i_].Lch = p2;T[N+i_].Rch = p1;T[p1].Parent = T[p2].Parent = N+i_;			
		}
		H[p1].weight = H[p2].weight = 0;H[N+i_].weight = T[N+i_].weight;
	}
	/*现在所得的T即为哈夫曼表*/
	for(int i_ = 1;i_ <= 2*N-1;i_++){
		printf("weight[%d]=%d\t",i_,T[i_].weight);
		printf("Parent[%d]=%d\t",i_,T[i_].Parent);
		printf("Lch[%d]=%d\t",i_,T[i_].Lch);
		printf("Rch[%d]=%d\n",i_,T[i_].Rch);
	}
	/*输出叶结点所对应的哈夫曼编码值*/
	for(int i_ = 1;i_ <= N;i_++){
		printf("%c = ",'A'+i_-1);
		Code(T,T[2*N-1].weight,N,i_);
		printf("\n");
	}
}

在这里插入图片描述
经验证与所画树的叶结点编码值相同 ! ^ _ ^ !

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值