`
bcyy
  • 浏览: 1823221 次
文章分类
社区版块
存档分类
最新评论

课程设计——赫夫曼编码

 
阅读更多

问题 J: 赫夫曼编码


题目描述

赫夫曼编码能够产生最短的报文。以报文“ABCDABCDABCABDABAA”为例,A编为0B对应10C对应110D对应111,整体的报文长度为35位二进制。相比于定长的ASCII码,压缩比达到了18*8/35=4.1

输入

输入有一系列的字符串组成,每个字符串占据一行。字符串仅包含大写字母和下划线。字符串“END”<wbr></wbr>表示处理结束,不应对其处理。

输出

对每一个字符串,输出其ASCII编码的比特位长度,赫夫曼编码的比特位长度,以及二者之比,精确到小数点后一位。

样例输入

ABCDABCDABCABDABAA<wbr></wbr>
AAAAAAAAAAAAAAAAAA
END

样例输出

144 35 4.1<wbr></wbr>
144 18 8.0


我费了九牛二虎之力,最终做了出来,代码如下,以作纪念:

#include <stdio.h>
#include<string.h>
#define N 100
#define MAX 1000
#define OK 1

typedef struct //huffman节点
{
char data;
int weight;//权值
int parent;//记录父结点下标
int lchild;//左孩子
int rchild;//右孩子
}HTNode;

int CreateHT(HTNode ht[],int n)//构造huffman树的代码没有一点错误
{

int i,k,lnode,rnode;
int min1,min2;
for(i=0;i<2*n-1;i++)
ht[i].parent=ht[i].lchild=ht[i].rchild=-1;
for(i=n;i<2*n-1;i++)
{
min1=min2=32767;
lnode=rnode=-1;//lnode和rnode为最小权重的两个节点的位置
for(k=0;k<=i-1;k++)
if(ht[k].parent==-1)//只在尚未构造二叉树的结点中查找
{
if(ht[k].weight<min1)//在节点中找到两个最小的,min1和min2记录下标
{
min2=min1;rnode=lnode;
min1=ht[k].weight;lnode=k;//记录下最小权重的下标
}
else if(ht[k].weight<min2)
{
min2=ht[k].weight;
rnode=k;
}
}
ht[lnode].parent=i;ht[rnode].parent=i;//更新父结点以及子节点的下标
ht[i].weight=ht[lnode].weight+ht[rnode].weight;
ht[i].lchild=lnode;ht[i].rchild=rnode;
}
return OK;
}

int AddNum(HTNode ht[],int hcd[],int k)
{
int i,f;
if(k==1)//结点分两种情况,一种是只有一个结点
{
hcd[0]=1;
return 0;
}
else//另一种是大于等于两个结点
{     for(i=0;i<k;i++)
{ 
  hcd[i]=0;
           f=ht[i].parent;
           while(f!=-1)//向上回溯寻找父结点,直至找到整棵树的根节点
  { 
  hcd[i]++;//父结点不为空,那数目就自增1(Huffman编码长度增1)
              f=ht[f].parent;
  }
   }
}
return OK;
}


int main()
{
    char str1[MAX];
    HTNode node[MAX];
int hcd[MAX];//用于记录每个编码的长度
int i,j,k,m;
float s;

while(1)
{    
k=0;
scanf("%s",str1);
if(strcmp(str1,"END")==0)  continue;
         for(i=0;str1[i]!='\0';i++)
{
node[i].weight=0;
             for(j=0;j<k;j++)//从第一位开始搜索,如果找到了相同的字符,那么该字符权值增1
  if(node[j].data==str1[i])
  {
   node[j].weight=node[j].weight+1;
   break;//找到了就不必再循环,读下一个字符
  }
  if(j==k)//没找到,就加入node数组
 {
  node[k].data=str1[i];
               node[k].weight=node[k].weight+1;
  k++;
 }
}//最后得到的k为字符的种类数目
m=i;//记录下i的值,i为输入的总字符的个数
        CreateHT(node,k);//构建一棵Huffman树
AddNum(node,hcd,k);//获取个个字符HUffman编码的长度
for(i=0,s=0.0;i<k;i++)
s=s+hcd[i]*node[i].weight;//获取用Huffman编码时总字符长度
printf("%d %.0f %.1f\n",m*8,s,m*8/s);
}
return 0;
}


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics