九度OJ-1172-哈夫曼树

九度OJ-1172-哈夫曼树

http://ac.jobdu.com/problem.php?pid=1172

哈夫曼树(Huffman tree):给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,即哈夫曼树

这题可以建树,也可以不建树。

建树:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define maxvalue 0x7fffffff
struct huffman
{
    int weight;
	int parent,lchild,rchild;
}list[5000];
int main()
{
	int n,m;
	int i,j;
	int ans;
	int x1,x2;
	int m1,m2;
	while(scanf("%d",&n)!=EOF)
	{
		m=2*n-1;
		for(i=0;i<m;i++)
		list[i].parent=list[i].lchild=list[i].rchild=-1;
		for(i=0;i<n;i++)
		scanf("%d",&list[i].weight);
		ans=0;
		for(i=0;i<n-1;i++)
		{
			x1=x2=0;
			m1=m2=maxvalue;
			for(j=0;j<n+i;j++)
			{
				if(list[j].weight<m1&&list[j].parent==-1)
				{
					x2=x1;
					m2=m1;
					x1=j;
					m1=list[j].weight;
				}
				else if(list[j].weight<m2&&list[j].parent==-1)
				{
					x2=j;
					m2=list[j].weight;
				}
			}
			list[x1].parent=n+i;
			list[x2].parent=n+i;
			list[n+i].lchild=x1;
			list[n+i].rchild=x2;
			list[n+i].weight=list[x1].weight+list[x2].weight;
			ans+=list[n+i].weight;
		}
		printf("%d\n",ans);
	}
	return 0;
}

不建树的简单一点:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int cmp(const void *a,const void *b)
{
	return *(int *)a-*(int *)b;
}
int main()
{
	int n,i,ans;
	int a[5000];
	while(scanf("%d",&n)!=EOF)
	{
		for(i=0;i<n;i++)
		scanf("%d",&a[i]);
		ans=0;
		for(i=0;i<n-1;i++)
		{
			qsort(a+i,n-i,sizeof(a[0]),cmp);
			ans+=(a[i]+a[i+1]);
			a[i+1]+=a[i];
		}
		printf("%d\n",ans);
	}
	return 0;
}

依据字符出现概率,可以利用哈夫曼树构造哈夫曼编码,写了个简易的代码:

给出26个字母的频度,执行哈夫曼编码,输入1编码,输入2译码。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define maxvalue 0x7fffffff
struct cam1
{
	char c;
	char s[50];
	int len;
}zimu[30];
struct cam2
{
	int weight;
	int parent,lchild,rchild;
}list[60];
void init()
{
	int i;
	for(i=0;i<26;i++)
	zimu[i].c='a'+i;
}
void huffmantree()
{
	int i,j;
	int x1,x2;
	int m1,m2;
	int pindu[26]={64,13,22,32,103,21,15,47,57,1,2,32,20,57,63,15,1,48,51,80,23,8,18,1,16,1};  //26个字母的频度
	for(i=0;i<60;i++)  
	list[i].parent=list[i].lchild=list[i].rchild=-1;
	for(i=0;i<26;i++)
	list[i].weight=pindu[i];
	for(i=0;i<25;i++)
	{
		x1=x2=0;
		m1=m2=maxvalue;
		for(j=0;j<26+i;j++)
		{
			if(list[j].weight<m1&&list[j].parent==-1)
			{
				x2=x1;
				m2=m1;
				x1=j;
				m1=list[j].weight;
			}
			else if(list[j].weight<m2&&list[j].parent==-1)
			{
				x2=j;
				m2=list[j].weight;
			}
		}
		list[26+i].lchild=x1;
		list[26+i].rchild=x2;
		list[x1].parent=list[x2].parent=26+i;
		list[26+i].weight=list[x1].weight+list[x2].weight;
	}
}
void huffmanbianma()
{
	int i,j,start;
	char s[100];
	int p,c,k;
	for(i=0;i<26;i++)
	{
		memset(s,0,sizeof(s));
		start=40;
		c=i;
		p=list[c].parent;
		while(p!=-1)
		{
			if(list[p].lchild==c)
			s[start]='0';
			else
			s[start]='1';
			start--;
			c=p;
			p=list[c].parent;
		}
		for(k=0,j=start+1;j<=40;k++,j++)
		zimu[i].s[k]=s[j];
		zimu[i].s[k]='\0';
		zimu[i].len=k;
	}
	printf("26个字母的哈夫曼编码如下:\n");
	for(i=0;i<26;i++)
	printf("%c----->%s\n",'a'+i,zimu[i].s);
}
int main()
{
	int i,j;
	int ans,len;
	char str[1000];
	int k1,k2,flag;
	printf("Welcome to Cambridgeacm\n");
	init();
	huffmantree();
	huffmanbianma();
	printf("输入1时执行编码\n");
	printf("输入2时执行译码\n");
	while(scanf("%d",&ans)!=EOF)
	{
		switch(ans)
		{
		    case 1:
			{
                 printf("请输入一段字符串\n");
                 scanf("%s",str);
				 len=strlen(str);
				 for(i=0;i<len;i++)
				 printf("%s",zimu[str[i]-'a'].s);
				 printf("\n");
				 printf("编码结束\n");
			}
			case 2:
			{
			     printf("请输入一段01代码\n");
				 scanf("%s",str);
                 len=strlen(str);
				 for(i=0;i<len;i++)
				 {
					 for(j=0;j<26;j++)
					 {
						 flag=1;
						 for(k1=i,k2=0;k1<=i+zimu[j].len-1&&str[k1]!='\0';k1++,k2++)
						 if(str[k1]!=zimu[j].s[k2])
						 {
							 flag=0;
							 break;
						 }
						 if(flag)
						 {
							 printf("%c",zimu[j].c);
							 i+=(zimu[j].len-1);
							 break;
						 }
					 }
				 }
				 printf("\n");
				 printf("译码结束\n");
			}
		}
	}
	return 0;
}

来个截图吧

九度OJ-1172-哈夫曼树




你可能感兴趣的:(哈夫曼树)