4赫夫曼编码文档格式.docx
《4赫夫曼编码文档格式.docx》由会员分享,可在线阅读,更多相关《4赫夫曼编码文档格式.docx(16页珍藏版)》请在冰豆网上搜索。
1概述
1.1现状分析
目前进行快速远距离通信的主要手段是电报,而电报通信的数码拨号时,我们常常会用到十进制,八进制,十六进制制数等。
而输入数字后,数据将以二进制数编码后进行远距离通信传送。
1.2存在的问题
在十进制,八进制,十六进制制数中往往为了提高通讯效率,会采用二进制数码尽可能短。
但每个字符设计长度不等的编码,让电文中出现多次数较多,这就造成大量的资源浪费。
1.3实现意义
利用赫夫曼编码进行通信可大大提高信道利用率,缩短信息传输时间,降低传输成本,减少代码错误率。
有效的数据压缩节省数据文件的存储空间和网络的传送时间。
2系统分析
实验先对输入的一串字符进行个数统计;
然后将各字符出现的频率作为各自的权值进行赫夫曼编码,并打印对应对的赫夫曼编码序列。
然后又对编码序列进行回译。
2.1实现功能
1.赫夫曼的建立;
2.赫夫曼编码的生成;
3.编码文件的译码;
2.2先是一个统计各字符的函数
intjsq(char*s,intcnt[],charstr[])
在其中定义一个数组temp[26]
即temp[0]表示A的频率;
同理
Temp[2]表示B的频率
依此类推;
函数最后返回值为字符串的种类。
2.3建立赫夫曼树的的算法
voidChuffmanTree(HuffmanTreeHT,HuffmanCodeHC,intcnt[],charstr[])
增加一个选择函数:
voidselect(HuffmanTreeT,intk,int*s1,int*s2)
即在对应的parent为0的结点中选取权值最小的两个结点
在建立赫夫曼树的算法中:
先对各节点初始化,对应的均为0;
在对叶子节点进行权值赋值;
选取两个parent为零的权值最小的两结点,将它们分为另一新结点的左右孩子,并将他们的权值和作为新结点的权值。
这样在结点中不断在选取,知道无法选取为止。
则赫夫曼树已经建立好。
2.4获得赫夫曼编码
voidHuffmanEncoding(HuffmanTreeHT,HuffmanCodeHC)
只需将对对应的叶子结点进行遍历,遇到是左子树则是0,右子树则为1;
对每个叶子结点进行又下到上遍历直到根节点即得到对应的逆编码,存入一个数组中,然后逆向打印。
即可。
2.5对对印的编码进行回译
只需逐个读取,直到符合某个字符的编码即打印出来,这样不断循环即可。
char*decode(HuffmanCodeHC)
3概要设计
4详细设计
4.1建立赫夫曼的三个函数
voidselect(HuffmanTreeT,intk,int*s1,int*s2)
{//在HT[1……k]中选择parent为0且权值最小的两个根结点,其序号分别为S1和S2
inti,j;
intmin1=100;
for(i=1;
i<
=k;
i++)//查找s1
if(T[i].weight<
min1&
&
T[i].parent==0)
{
j=i;
min1=T[i].weight;
}
(*s1)=j;
min1=32767;
i++)//查找s2,不和s1相同
T[i].parent==0&
i!
=(*s1))
min1=T[i].weight;
(*s2)=j;
}
{
char*p;
inti,j,k;
inttemp[27];
=26;
i++)
temp[i]=0;
for(p=s;
*p!
='
\0'
;
p++)
{//统计各种字符个数
if(*p>
A'
&
*p<
Z'
){
k=*p-64;
temp[k]++;
j=0;
for(i=1,j=0;
i++)//统计有多少种字符
if(temp[i]!
=0){
j++;
str[j]=i+64;
//将对应的数组送到数组中
cnt[j]=temp[i];
//存入对应数组的权值
returnj;
{//构造赫夫曼树HT
inti,s1,s2;
=2*num-1;
i++)//初始化HT,左右孩子,双亲,权值都为0
{HT[i].lchild=0;
HT[i].rchild=0;
HT[i].parent=0;
HT[i].weight=0;
=num;
i++)//输入num个叶节点的权值
HT[i].weight=cnt[i];
for(i=num+1;
i++)//从numd后面开始新建结点存放新生成的父节点
HT[s1].parent=i;
HT[s2].parent=i;
//将s1和s2的parent赋值
HT[i].lchild=s1;
HT[i].rchild=s2;
//新结点的左右孩子
HT[i].weight=HT[s1].weight+HT[s2].weight;
//新结点的权值
for(i=0;
i++)//输入字符集中的字符
HC[i].ch=str[i];
i=1;
while(i<
=num)
printf("
字符%c,次数为:
%d\n"
HC[i].ch,cnt[i++]);
4.2生成赫夫曼编码文件的两个函数
voidHuffmanEncoding(HuffmanTreeHT,HuffmanCodeHC)
{//根据赫夫曼树HT求赫夫曼编码表HC
intc,p,i,j;
//c和p分别指示T中孩子和双亲的位置
charcd[n];
//临时存放编码串
intstart;
//指示编码在cd中的起始位置
cd[num]='
//最后一位放上串结束符
start=num;
//初始位置
c=i;
//从叶子节点T[i]开始上溯
while((p=HT[c].parent)>
0)//直至上溯到HT[c]是树根为止
{//若T[c]是T[p]的做孩子,则生成0;
否则生成代码1
cd[--start]=(HT[p].lchild==c)?
'
0'
:
1'
//cd数组用来存放每一个字母对应的01编码,
c=p;
}//while结束
strcpy(HC[i].bits,&
cd[start]);
//将cd数组中德01代码复制到i结点中
字符%c:
"
HC[i].ch);
for(j=start;
cd[j]!
=0;
j++)
%c"
cd[j]);
\n"
);
HC[i].len=num-start;
}//for结束
voidcoding(HuffmanCodeHC,char*str)
{//对str所代表的字符串进行编码,并写入文件
FILE*fp;
fp=fopen("
codefile.txt"
"
w"
while(*str){
if(HC[i].ch==*str){
for(j=0;
j<
HC[i].len;
j++){
fputc(HC[i].bits[j],fp);
break;
str++;
fclose(fp);
4.3电文的译码
char*decode(HuffmanCodeHC)
{//代码文件coodfile.txt的译码*菡枫*
charstr[254];
//假设原文本文件不超过254个字符
char*p;
staticcharcd[n+1];
inti,j,k=0,cjs;
r"
//读文件
编码后的文件为:
while(!
feof(fp))
{cjs=0;
num&
cjs==0&
!
feof(fp);
cd[i]='
cd[i+1]='
cd[i]=fgetc(fp);
cd[i]);
//打印出编码后的二进制码
for(j=1;
if(strcmp(HC[j].bits,cd)==0)
str[k]=HC[j].ch;
k++;
cjs=1;
str[k]='
p=str;
returnp;
4.4主函数
voidmain(){
charst[254],*s,str[27];
intcn[27];
HuffmanTreeHT;
HuffmanCodeHC;
输入需要编码的字符串(假设均为大写字母):
\n"
gets(st);
num=jsq(st,cn,str);
//统计字符的种类及各类字符出现的频率
ChuffmanTree(HT,HC,cn,str);
//建立赫夫曼树
HuffmanEncoding(HT,HC);
//生成赫夫曼编码
coding(HC,st);
//建立电文赫夫曼编码文件
s=decode(HC);
//读编码文件译码*菡枫*
译码后的字符串:
%s\n"
s);
5运行与测试
6总结和心得
在这次的试验中,让我更深的了解数据结构,在做实验的时候,自己亲自动手,一点一点慢慢做,突然发现好困难,也由于平时的基本功不够,所以导致了问题的难度性加大了。
在这次的试验中,难易程度对我而言较大,程序代码难度有点大,但由于输入时不细心,导致许多的小错误,还存在着不少的问题,在同学的帮助下,慢慢解决了这个问题,但许多概念还是模棱两可的
但是,这次绝对是我的一个进步。
我以后一定认真学习,好好把握问题的关键,掌握知识的要领。
7参考文献
[1].严蔚敏、吴伟民主编《数据结构》(C语言版)清华大学出版社
[2]苏仕华主编《数据结构课程设计》机械工业出版社
[3]