2010北邮上机真题——哈夫曼树

题目描述:
哈夫曼树,第一行输入一个数n,表示叶结点的个数。需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和。

输入:
输入有多组数据。
每组第一行输入一个数n,接着输入n个叶节点(叶节点权值不超过100,2<=n<=1000)。

输出:
输出权值。

样例输入:
5
1 2 2 5 9
样例输出:
37

#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_;
}
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);
	}
	//此时得到的T结构体数组即为哈夫曼表
	/*重新排列哈夫曼表的顺序*/
	for(i = 1;i <= 2*N-1;i++){
		for(int i_ = i;i_ <= 2*N-1;i_++){
			if(T[i].weight < T[i_].weight){
				HTNode P = T[i];
				T[i] = T[i_];
				T[i_] = P;
			}
		}
	}
	int Sum = 0;
	for(i = 1;i <= 2*N-1;i++){
		if(T[i].Lch == 0){
			Sum += (T[i].weight)*(i/2);
		}
	}
	printf("\n");
	printf("Sum = %d",Sum);
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值