题目编写一个哈夫曼译码器模拟程序.docx
《题目编写一个哈夫曼译码器模拟程序.docx》由会员分享,可在线阅读,更多相关《题目编写一个哈夫曼译码器模拟程序.docx(15页珍藏版)》请在冰豆网上搜索。
题目编写一个哈夫曼译码器模拟程序
题目:
编写一个哈夫曼/译码器模拟程序
班级:
031016姓名:
王君学号:
03101612完成日期:
2005-10-10
需求分析
1.利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本,本程序要求将一些代码用哈夫曼编码进行编码。
矚慫润厲钐瘗睞枥庑赖賃軔。
2.首先要对输入的字符和响应的统计使用频率进行编码,将编好的代码放入响应的文件当中,当绎码时,读出要译的原码利用已编好的哈夫曼进行绎码。
聞創沟燴鐺險爱氇谴净祸測。
3.测试数据
(1)利用教科书例6-2的数据调试程序。
(2)用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:
“THISPROGRAMISMYFAVORITE”残骛楼諍锩瀨濟溆塹籟婭骒。
字符
ABCDEFGHIJKLM
频度
1836413223210321154757153220
字符
NOPQRSTUVWXYZ
频度
5763151485180238181161
二.概要设计
1.堆栈的抽象数据类型定义为:
ADTBinaryTree{
数据对象D:
D是具有特性的数据元素的集合。
数据关系R:
若D=⊙,则R也是空,称BinaryTree为空二叉树;
若D不等空,则R={H},H是如下二元关系;
在D中存在唯一的称为根的数据元素root,它在关系H下无前驱;
若D-{root}不等于空,则存在D-{root}={D1,D2},且D!
∩D2=空;
若D1不为空,则D1中存在唯一的元素x1,∈H,且存在Dr上的关系Hr∈H;H={,,H1,Hr};酽锕极額閉镇桧猪訣锥顧荭。
(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
本程序包含三个模块:
主程序模块;
voidmain()
{
初始二叉树;
do{
接受命令;
处理命令;
}while(“命令”==”推出”)
}
编码模块。
译码模块。
主程序模块
编码模块
译码模块
详细设计
#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<!
!
**********"<}//½áÊø
函数的调用关系图反映了演示程序的层次结构:
main()
HuffmanCoding();
Encoding();Decoding(HC,c,27);print();
调试分析
本程序最主要的是如何创建哈夫曼树进行编码和译码,在创建哈夫曼树时对数据进行了分析,首先根据字符的频度进行创建哈夫曼树,将编好的编码放入到固定的文件当中,再读取需要编译的字符串进行编码放入到文件当中,然后对编码进行译码,译码主要是根据已经创建好的哈夫曼对其译码。
怂阐譜鯪迳導嘯畫長凉馴鸨。
在数据处理时遇到一些程序调试上的困难,最大的困难在译码的函数中如何对一串字符进行逐个的译码,经过仔细的分析数据,终于找到了合适的算法对它进行译码。
谚辞調担鈧谄动禪泻類谨觋。
调试中出现很多小的错误,比如函数调用的数据比匹配,定义错误,还有输出格式的控制等,这些错误后来都经过仔细的调试编译都调试通过了。
数据输出基本上都正确。
嘰觐詿缧铴嗫偽純铪锩癱恳。
在本程序中,输入输出相对来说比较简单,在创建哈夫曼树上花费了不少时间,但相对来说还是难度教小,最主要的是理解哈夫曼树的本质原理。
熒绐譏钲鏌觶鷹緇機库圆鍰。
本程序的时间和空间复杂度分析:
数据的读入首先放到两个数组当中,然后最每个数据进行判断,由于哈夫曼编码效率很高,所以时间复杂度上相对较好。
在空间上,数据存放在两个数组当中需先申请相应的空间,会有空间浪费,但相对来说是比较少的。
鶼渍螻偉阅劍鲰腎邏蘞阕簣。
本实习作业采用数据抽象的程序设计方法,将程序分为三个层次结构:
编码结构,译码模块,主程序模块,使得设计时思路清晰,实现时调试顺利,各模块具有较好的可重用性,确实得到了一次良好的程序设计训练。
纣忧蔣氳頑莶驅藥悯骛覲僨。
用户手册
本程序的运行环境为DOS操作系统,执行文件为:
哈夫曼_译码器.exe。
进入演示程序后显示的文本方式的用户截面:
测试结果
输入数据:
字符
ABCDEFGHIJKLM
频度
1836413223210321154757153220
字符
NOPQRSTUVWXYZ
频度
5763151485180238181161
输出如下:
结果正确符合要求!