哈夫曼树与哈夫曼编码

利用哈夫曼编码进行通信可以大大提高信道的利用率,缩短信息传输的时间,降低传输成本。根据哈夫曼编码的原理,编写一个程序,在用户输入结点权值的基础上求哈夫曼编码。 

设计要求:从键盘输入若干字符及每个字符出现的频率,将字符出现的频率作为结点的权值,建立哈夫曼树,然后对各个字符进行哈夫曼编码,最后打印输出字符及对应的哈夫曼编码。

求最佳答案。


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 80
typedef struct
{
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree;//动态分配数组存储赫夫曼树
typedef char * *HuffmanCode;//动态分配数组存储赫夫曼编码表
void Select(HuffmanTree &HT,int &i,int &s1,int s2);
//从i个节点中选出parent为0且weight最小的两个结点,其序号分别为s1和s2
void reverse(char a[],int &b);//把字符串逆置
void Huffmancoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int &n)
//存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码 HC

int m,i;
if(n<=1)return;
m=2*n-1;//赫夫曼树的结点总数
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));// 0号单元未用
HuffmanTree p;
p=NULL;
for(p=HT+1,i=1;i<=n;++i,++p,++w)
//构造n颗只有根结点的树,因0号单元未用,因此p指向HT+1
{
p->weight=*w;p->parent=0;p->lchild=0;p->rchild=0;

for(i=n+1;i<=m;++i,++p)
//新生成的结点各值都赋值为0
{
p->weight=0;p->parent=0;p->lchild=0;p->rchild=0;

printf("初态:\n");
printf("node\tweight\tparent\tlchild\trchild\n"); p=HT+1;
for(i=1;i<=m;i++,++p)
{
printf("%d\t%d\t%d\t%d\t%d\n",i,p->weight,p->parent,p->lchild,p->rchild);
}
printf("\n");
int s1,s2,t;//s1,s2分别为最小和次小结点
for(i=n+1;i<=m;++i)
//建赫夫曼树
{
t=i-1;//便于实参传递,因此把i-1赋值给t
s1=s2=0;Select(HT,t,s1,s2);//选择最小和次小结点
HT[s1].parent=i;
HT[s2].parent=i;
HT[i].lchild=s1;
HT[i].rchild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight; 
}printf("终态:\n");
printf("node\tweight\tparent\tlchild\trchild\n");
p=HT+1;
for(i=1;i<=m;i++,++p)
{
printf("%d\t%d\t%d\t%d\t%d\n",i,p->weight,p->parent,p->lchild,p->rchild);
}printf("\n");//从叶子到根逆向求每个字符的赫夫曼编码
int start,k;
unsigned int c,f;
char *cd;cd=NULL;
HC=(HuffmanCode)malloc((n+1)*sizeof(char *));//分配n个字符编码的头指针向量,0号单元未用
cd=(char *)malloc(n*sizeof(char));//分配求编码的临时工作空间
void reverse(char a[],int &b);//把字符串逆置
for(i=1;i<=n;++i) 
//逐个字符求赫夫曼编码 
{
start=0;//从各个叶子结点到根结点的逆序编码依次存入 cd,start为编码开始府
for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)
if(HT[f].lchild==c)cd[start++]='0';
else
cd[start++]='1';
cd[start]='\0';//编码结束符'\0'存入cd*
k=strlen(cd);//k为存入cd的编码的长度
reserve(cd,k);//把逆序存入的编码再逆置,此时cd中存入的即为从根结点到叶子结点的正序编码
HC[i]=(char*)malloc((n-start)*sizeof(char));//为第i个字符编码分配空间
strcpy(HC[i],cd);//从cd复制编码(串)到HC[i]

free(cd);//释放工作空间

void Select(HuffmanTree &HT,int &i,int &s1,int &s2)
{
unsigned int m1,m2;
int k;
m1=m2=32767;//*m1,m2为最小和次小结点权值
for(k=1;k<=i;k++)
{
if((HT[k].parent==0)&&(HT[k].weight<m1))
{
m2=m1;
s2=s1;
m1=HT[k].weight;
s1=k;
}
else if((HT[k].parent==0)&&(HT[k].weight<m2))
{
m2=HT[k].weight;s2=k;
}


void reserve(char a[],int &b)
{
char t,*p=a;
for(int i=0,j=b-1;i<b/2;i++,j--)
{
t=*(p+i);
*(p+i)=*(p+j);
*(p+j)=t;
}
}
int main()
{
char u[N],str[N];
int i,n,k,w[N];
HuffmanTree HT;
HuffmanCode HC;
printf("输入字符的个数:");
scanf("%d",&n);
printf("分别输入这%d个字符:\n",n);
for(i=0;i<n;i++)
{
scanf("%c",&u[i]);
getchar();

printf("存放上述所输入\“字符\”的哈夫曼树的数组HT的状态如下:\n");
Huffmancoding(HT,HC,w,n);
    printf("以下是每个字符所对应的哈夫曼编码是:\n");
    for (i=1; i<=n; ++i)
    {
    printf("第%d 个字符所对应的哈夫曼编码是:",i);
    printf("%s\n",HC[i]);
    }
    printf("\n");
    printf("(把上次输入的每个字符再依次输入,并存到 str 字符串中)\n");
    printf("请输入:");
    scanf("%s",str);
    k=strlen(str);
    printf("字符串%s 所对应的\"电文编码\"是:",str);
    for (i=1; i<=n; ++i)
    printf("%s",HC[i]);
    printf("\n"); 
}


[Error] E:\zsyc\h1226.cpp:74: error: `reserve' was not declared in this scope

求大神多多指教,感激不尽!




  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值