《编写一个哈夫曼译码器模拟程序》实习报告.docx
《《编写一个哈夫曼译码器模拟程序》实习报告.docx》由会员分享,可在线阅读,更多相关《《编写一个哈夫曼译码器模拟程序》实习报告.docx(18页珍藏版)》请在冰豆网上搜索。
《编写一个哈夫曼译码器模拟程序》实习报告
题目:
编写一个哈夫曼/译码器模拟程序
班级:
姓名:
学号:
一.
二.需求分析
1.利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本,本程序要求将一些代码用哈夫曼编码进行编码。
2.首先要对输入的字符和响应的统计使用频率进行编码,将编好的代码放入响应的文件当中,当绎码时,读出要译的原码利用已编好的哈夫曼进行绎码。
3.测试数据
(1)利用教科书例6-2的数据调试程序。
(2)用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:
“THISPROGRAMISMYFAVORITE”
字符
ABCDEFGHIJKLM
频度
1836413223210321154757153220
字符
NOPQRSTUVWXYZ
频度
5763151485180238181161
二.概要设计
1.堆栈的抽象数据类型定义为:
ADTBinaryTree{
数据对象D:
D是具有特性的数据元素的集合。
数据关系R:
若D=⊙,则R也是空,称BinaryTree为空二叉树;
若D不等空,则R={H},H是如下二元关系;
(1)在D中存在唯一的称为根的数据元素root,它在关系H下无前驱;
(2)若D-{root}不等于空,则存在D-{root}={D1,D2},且D!
∩D2=空;
(3)若D1不为空,则D1中存在唯一的元素x1,∈H,且存在Dr上的关系Hr∈H;H={,,H1,Hr};
(4)(D1,{H1})是一棵符合定义的二叉树,称为根的左子树,{Dr,{Hr}}是一棵符合本定义的二叉树,称为根的右子树。
数据操作:
InitBiTree(&T);
操作结果:
构造空的二叉树。
DestroyBiTree(&T)
初始条件:
二叉树T存在。
操作结果:
销毁二叉树T.
CreatebiTree(&T,definition);
初始条件:
definition给出二叉树T的定义。
操作结果:
按definition构造二叉树T。
ClearBiTree(&T)
初始条件:
二叉树T存在。
操作结果:
将二叉树T清为空树。
BiTreeEmpty(T);
初始条件:
二叉树T存在。
操作结果:
返回T深度。
Root(T);
初始条件:
二叉树T存在。
操作荚果:
返回T的根。
Value(T,e);
初始条件:
二叉树T存在,e是t中某个结点。
操作结果:
返回e的值。
Assign(T,&e,value)
初始条件:
二叉树T存在,e是t中某个结点。
操作结果:
结点e赋值为valuel。
}ADTBinaryTree
本程序包含三个模块:
1)主程序模块;
voidmain()
{
初始二叉树;
do{
接受命令;
处理命令;
}while(“命令”==”推出”)
}
2)编码模块。
3)译码模块。
主程序模块
编码模块
译码模块
三.详细设计
#include
#include
#include
#include
#include
#include
usingnamespacestd;
ints1=0,s2=0;//¶¨Òås1£¬s2Ϊȫ¾Ö±äÁ¿
//¶ÔÊý¾Ý½á¹¹½øÐж¨Òå
typedefstruct
{
intweight;
intparent,lchild,rchild;
}HTNode,*HuffmanTree;
typedefchar**HuffmanCode;
//¶¨Òå½áÊø
//¶ÁÈëÊý¾Ý
voidcreat(int*w,char*c)
{
charch;
intn,i;
ifstreamfin("hfmTree.txt");
for(i=1;i<=27;i++)
{
ch=fin.get();
fin>>n;
w[i]=n;c[i]=ch;
}
cout<<"¶ÁÈëÊý¾ÝÈçÏ£º"<for(i=1;i<=27;i++)
{
cout<<"×Ö·û:
"<"<if(i%4==0)
cout<}
cout<cout<<"Êý¾ÝÒѾ¶ÁÈëÍê±Ï,¿ÉÒÔ½øÐбàÂë"<}
//----------------------¶¨Òåselectº¯Êý-----------------------//
voidSelect(HTNode*HT,intn)
{
inti;
HTNode*p;
p=HT;
for(i=1;i<=n;i++)//ÕÒµÚÒ»¸öË«Çײ»Îª0µÄ½Úµã
if((p+i-1)->parent==0)
{
s1=i;
break;
}
for(i=1;i<=n;i++)//ÕÒµÚ¶þ¸öË«Çײ»Îª0µÄ½Úµã
if(i!
=s1&&(p+i-1)->parent==0)
{
s2=i;
break;
}
for(i=1;i<=n;i++)//ÕÒ³ö×îСµÄs1½Úµã
if((p+i-1)->weight<(p+s1-1)->weight&&(p+i-1)->parent==0)
if(i==s2)
{
s2=s1;
s1=i;
}
else
s1=i;
for(i=1;i<=n;i++)//ÕÒ³ö×îСµÄs2½Úµã
if(i!
=s1&&(p+i-1)->weight<(p+s2-1)->weight&&(p+i-1)->parent==0)
s2=i;
}//--------------------¶¨Ò幦ÄܽáÊø----------------------------//
//---------------------¶ÔÎļþ½øÐбàÂë-------------------------//
voidEncoding(HuffmanCodeHC,char*d,intn)
{
charch;
inti;
ifstreamfin("ToBeTran.txt");//¶ÁÈëÒª½øÐбàÂëµÄÎļþÄÚÈÝ
ofstreamfout("CodePrin.txt");//°Ñ±àÂëÊäÈëµ½ÎļþÖÐ
ch=fin.get();//¶ÁÈë×Ö·û
while(ch!
=EOF)
{
for(i=1;i<=n;i++)
if(d[i]==ch)
break;
fout<ch=fin.get();
}
fin.close();
fout.close();
}
//-------------------------------------------------------------//
voidDecoding(HuffmanCodeHC,char*w,intk)
{
ifstreamfin("CodePrin.txt");//¶ÁÈëÒªÒëÂëµÄÎļþ
ofstreamfout("TextFile.txt");//½«´úÂëÒëÂëºó·ÅÈëµ½ÎļþÖÐ
charstr[20];
charc[200],ch;
inti=0,j=1,n,m,t;
ch=fin.get();
while(ch!
=EOF)//¶ÁÈëµ½Êý×éÖÐ
{
c[++i]=ch;
ch=fin.get();
}
while(j
{
for(n=1;n<=k;n++)
{
t=strlen(HC[n]);
for(m=1;m<=t;m++)
str[m-1]=c[m+j-1];
str[m-1]='\0';
if(strcmp(str,HC[n])==0)
{
fout<break;
}
}
j+=strlen(HC[n]);
}
fin.close();//¹Ø±ÕÎļþ
fout.close();
}//Decoding
//-------------------------------------------------------------//
//-----------------------Êä³ö±àÂë------------------------------//
voidprint()
{
ifstreamfin("CodePrin.txt");//´ò¿ªÎļþ
ifstreamfi("ToBeTran.txt");
charch;
inti=0;
cout<<"Ô´úÂëÊÇ£º"<ch=fi.get();
while(ch!
=EOF)
{
cout<ch=fi.get();
}
cout<cout<<"ÒëÂëºóµÄ´úÂëÊÇ£º"<ch=fin.get();
while(ch!
=EOF)
{
cout<++i;
if(i%50==0)
cout<ch=fin.get();
}
fin.close();
cout<}
//--------------------------------------------------------------//
//*************************************************************//
//*********************½øÐкշòÂü±àÂë**************************//
voidHuffmanCoding(HTNode*HT,HuffmanCode&HC,int*w,intn,char*d)
{
ifstreamfin("ToBeTran.txt");
intm,i,start,f;
intc;
floatsum=0;
char*cd;
HTNode*p;
if(n<=1)return;//Èç¹ûnµÈÓÚ1£¬Ö±½Ó·µ»Ø
m=2*n-1;//mÊÇÒªÔö¼ÓµÄ½ÚµãÊý
HT=(HTNode*)malloc((m+1)*sizeof(HTNode));
for(p=HT,i=1;i<=n;++i)//³õʼ»¯±íÔªËØ
{
(p+i-1)->weight=w[i];
(p+i-1)->parent=0;
(p+i-1)->lchild=0;
(p+i-1)->rchild=0;
}
for(;i<=m;++i)
{
(p+i-1)->weight=0;
(p+i-1)->parent=0;
(p+i-1)->lchild=0;
(p+i-1)->rchild=0;
}//³õʼ»¯½áÊø
for(i=n+1;i<=m;++i)//Ñ°ÕÒ¸÷×ÔµÄË«Ç×ÒÔ¼°º¢×Ó½Úµã
{
Select(HT,i-1);
(p+s1-1)->parent=i;(p+s2-1)->parent=i;
(p+i-1)->lchild=s1;(p+i-1)->rchild=s2;
(p+i-1)->weight=(p+s1-1)->weight+(p+s2-1)->weight;
}//½áÊø
HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
cd=(char*)malloc(n*sizeof(char));
cd[n-1]='\0';
for(i=1;i<=n;++i)//È·¶¨Ã¿¸öÔªËصıàÂë
{
start=n-1;
for(c=i,f=(p+i-1)->parent;f!
=0;c=f,f=(p+f-1)->parent)
if((p+f-1)->lchild==c)
cd[--start]='0';
else
cd[--start]='1';
HC[i]=(char*)malloc((n-start)*sizeof(char));
strcpy(HC[i],&cd[start]);
//Êä³öÔªËصıàÂë
cout<cout<cout<<"";
if(i%2==0)
cout<}//È·¶¨½áÊø
fin.close();
cout<free(cd);//ÊÍ·Åcd½Úµã
}//º¯Êý½áÊø
//*********************************************************//
//--------------------------Ö÷º¯Êý--------------------------//
voidmain()
{
intw[28];
charc[28];
charch;
HTNode*HT={0};//³õʼ»¯ÔªËØ
HuffmanCodeHC={0};
//cout<<"ÇëÊäÈëÒª½øÐбàÂëµÄ¸öÊý:
";
/*cin>>num;//¶ÁÈëÊý¾Ý
for(i=1;i<=num;i++)
{
cout<<"ÊäÈëµÚ"<
cin>>w[i];
cout<}*/
cout<<"******************¹þ·òÂü/ÒëÂëÆ÷******************"<cout<<"--------²Ù×÷ָʾ---------------------------------"<cout<<"I:
¶ÁÈëÊý¾Ý.E:
½øÐбàÂë.D:
ÒëÂë.P:
´òÓ¡ÂëÎļþ."<cout<<"------------------------------------------------"<cout<<"°´QÍ˳ö"<cout<<"ÇëÊäÈë²Ù×÷·û£º";
ch=cin.get();
while(ch!
='Q')
{
switch(ch)
{
case'I':
creat(w,c);cout<<"ÇëÊäÈë²Ù×÷·û£º";break;
case'E':
cout<<"¹þ·òÂü±àÂëÈçÏ£º"<case'D':
Decoding(HC,c,27);cout<"<case'P':
print();cout<<"ÇëÊäÈë²Ù×÷·û£º";break;
default:
break;
}
//¿ªÊ¼±àÂ룬²¢Êä³ö
ch=cin.get();
}
cout<cout<!
!
**********"<}//½áÊø
1.函数的调用关系图反映了演示程序的层次结构:
main()
HuffmanCoding();
Encoding();Decoding(HC,c,27);print();
调试分析
1.本程序最主要的是如何创建哈夫曼树进行编码和译码,在创建哈夫曼树时对数据进行了分析,首先根据字符的频度进行创建哈夫曼树,将编好的编码放入到固定的文件当中,再读取需要编译的字符串进行编码放入到文件当中,然后对编码进行译码,译码主要是根据已经创建好的哈夫曼对其译码。
2.在数据处理时遇到一些程序调试上的困难,最大的困难在译码的函数中如何对一串字符进行逐个的译码,经过仔细的分析数据,终于找到了合适的算法对它进行译码。
3.调试中出现很多小的错误,比如函数调用的数据比匹配,定义错误,还有输出格式的控制等,这些错误后来都经过仔细的调试编译都调试通过了。
数据输出基本上都正确。
4.在本程序中,输入输出相对来说比较简单,在创建哈夫曼树上花费了不少时间,但相对来说还是难度教小,最主要的是理解哈夫曼树的本质原理。
5.本程序的时间和空间复杂度分析:
数据的读入首先放到两个数组当中,然后最每个数据进行判断,由于哈夫曼编码效率很高,所以时间复杂度上相对较好。
在空间上,数据存放在两个数组当中需先申请相应的空间,会有空间浪费,但相对来说是比较少的。
6.本实习作业采用数据抽象的程序设计方法,将程序分为三个层次结构:
编码结构,译码模块,主程序模块,使得设计时思路清晰,实现时调试顺利,各模块具有较好的可重用性,确实得到了一次良好的程序设计训练。
四.用户手册
1.本程序的运行环境为DOS操作系统,执行文件为:
哈夫曼_译码器.exe。
2.进入演示程序后显示的文本方式的用户截面:
测试结果
输入数据:
字符
ABCDEFGHIJKLM
频度
1836413223210321154757153220
字符
NOPQRSTUVWXYZ
频度
5763151485180238181161
输出如下:
结果正确符合要求!