您的位置:首页 > 其它

九度OJ-1172-哈夫曼树

2012-06-20 09:24 429 查看
九度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;
}


来个截图吧

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: