1760 Problem A 算法6-12:自底向上的赫夫曼编码

问题 A: 算法6-12:自底向上的赫夫曼编码

时间限制: 1 Sec  内存限制: 32 MB
提交: 26  解决: 13
 

在通讯领域,经常需要将需要传送的文字转换成由二进制字符组成的字符串。在实际应用中,由于总是希望被传送的内容总长尽可能的短,如果对每个字符设计长度不等的编码,且让内容中出现次数较多的字符采用尽可能短的编码,则整个内容的总长便可以减少。另外,需要保证任何一个字符的编码都不是另一个字符的编码前缀,这种编码成为前缀编码。

而赫夫曼编码就是一种二进制前缀编码,其从叶子到根(自底向上)逆向求出每个字符的算法可以表示如下:

在本题中,读入n个字符所对应的权值,生成赫夫曼编码,并依次输出计算出的每一个赫夫曼编码。

 

输入

输入的第一行包含一个正整数n,表示共有n个字符需要编码。其中n不超过100。

第二行中有n个用空格隔开的正整数,分别表示n个字符的权值。

输出

共n行,每行一个字符串,表示对应字符的赫夫曼编码。

样例输入

8
5 29 7 8 14 23 3 11

样例输出

0110
10
1110
1111
110
00
0111
010

提示

赫夫曼树又名最优二叉树,它是一类带权路径长度最小的二叉树。通过构造赫夫曼树,我们可以得到赫夫曼编码,从而使得通信能够得到更高的效率。在本题中,构造赫夫曼树的过程使用了从叶子到根的逆向顺序,另外,还有一种从根出发直到叶子的赫夫曼编码构造算法,这将在下一题中进行讨论。

经验总结

看代码吧= = 要学习这个代码结构,从大佬那里弄来的,真进行哈夫曼编码确实要进行建树,而编码方法有两种,这只是第一种,理解并且要学会自己写,就行啦~~

正确代码

#include <cstdio>
#include <climits>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=110;
struct HuffNode
{
	int w,parent,lchild,rchild;
}Node[maxn*2];
void SearchMin(int &a,int &b,int n)
{
	int min=INT_MAX;
	for(int i=0;i<n;++i)
	{
		if(Node[i].parent==0&&Node[i].w<min)
		{
			min=Node[i].w;
			a=i;
		}
	}
	min=INT_MAX;
	for(int i=0;i<n;++i)
	{
		if(Node[i].parent==0&&Node[i].w<min&&i!=a)
		{
			min=Node[i].w;
			b=i;
		}
	}
	if(a>b)
	{
		swap(a,b);
	}
}
void HuffmanCode(int n,int * w,char * * &ans)
{
	for(int i=0;i<n;++i)
	{
		Node[i].parent=Node[i].lchild=Node[i].rchild=0;
		Node[i].w=w[i];
	}
	for(int i=n;i<2*n-1;++i)
	{
		int a,b;
		SearchMin(a,b,i);
		Node[i].lchild=a;
		Node[i].rchild=b;
		Node[i].w=Node[a].w+Node[b].w;
		Node[a].parent=Node[b].parent=i;
	}
	int c,f,index;
	char temp[n];
	ans=new char * [n];
	for(int i=0;i<n;++i)
	{
		c=i;
		index=n-1;
		temp[index]=0;
		while(Node[c].parent!=0)
		{
			f=Node[c].parent;
			if(Node[f].lchild==c)
				temp[--index]='0';
			else
				temp[--index]='1';
			c=f;
		}
		ans[i]=new char[n-index];
		strcpy(ans[i],temp+index);
	}
}
int main()
{
	int n,w[maxn];
	char * * ans;
	while(~scanf("%d",&n))
	{
		for(int i=0;i<n;++i)
		{
			scanf("%d",&w[i]);
		}
		HuffmanCode(n,w,ans);
		for(int i=0;i<n;++i)
		{
			printf("%s\n",ans[i]);
		}
	}
	delete ans;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a845717607/article/details/81671832