哈弗曼编码课程设计实验报告.docx
《哈弗曼编码课程设计实验报告.docx》由会员分享,可在线阅读,更多相关《哈弗曼编码课程设计实验报告.docx(29页珍藏版)》请在冰豆网上搜索。

哈弗曼编码课程设计实验报告
一、实训要求……………………………………………………………………………..2
二、课题分析和设计……………………………………………………………………..2
1、基本需求分析……………………………………………………………………2,3
2、对应的类………………………………………………………………................3,4,5
三、主要功能界面………………………………………………………………………...5
1、主界面……………………………………………………………………………5
2、读取文章并对字符编码…………………………………………………………5
3、哈弗曼编码信息………………………………………………………………….6
4、文章编码………………………………………………………………………….6
5、文章译码………………………………………………………………………….6
6、错误处理………………………………………………………………………….7
四、总结(课设心得体会)………………………………………………………………7
五、附录(主要函数代码)………………………………………………………………7~14
一、实训要求
1、输入为:
一段中文或英文的文章的文件名。
2、读取文章的字符信息。
3、对字符进行权值的计算。
4、根据权值构造哈弗曼树。
5、生成对应的编码。
6、输出为:
原文章的编译(译文)。
7、根据已经生成的编码表,输入任意的译文可以得到原文。
二、课题分析和设计
1.基本需求分析:
(1)在通信过程中,为了提高信道利用率,缩短信息传输时间降低传输成本,需要一编译码器。
(2)此哈弗曼编码译码器应具有编码译码的双向功能,即在发送端通过编码系统对传入的数据进行编码。
(3)在接收端将数据译码,将具有两项功能的编码译码器用于双工信道就可满足,双工信道的双向编译功能。
(4)输入某段报文是,系统将自己完成编译输出。
(5)、程序设计流程:
<1>文字表述:
开始进入功能选择界面,包含五种操作
(1)读取文章并对字符编码。
(2)哈夫曼编码信息。
(3)文章编码。
(4)文章译码。
(5)退出程序。
<2>操作:
(1)给定一篇文章,统计字符出现的概率,并根据概率建立哈弗曼树,并利用哈弗曼树对字符进哈夫曼编码。
(2)显示哈弗曼编码信息,包括字符和其哈弗曼编码。
(3)对文章进行译码,显示译码信息,并保存。
(4)对文章进行译码,显示并保存。
<3>流程图:
2、对应的类:
<1>定义类:
classElement//结点类
{
public:
charname;//字符名
intweight;//字符权值
intlchild;//左孩子
intrchild;//右孩子
intparent;//父结点
Element()
{
weight=0;
lchild=-1;
rchild=-1;
parent=-1;
}
~Element(){}
};
<2>定义字符和出现的次数:
className//字符类
{
public:
charpname;//字符名
intnum;//字符出现的次数
doublelweight;//字符的权值
Name()
{
num=0;
lweight=0;
}
~Name(){}
};
<3>定义字符总类总数和存储信息:
classGetName//关于字符类
{
public:
charfile_name[max2];//文件名
intn;//字符的种类
intsum;//字符的总数
Nameletter[max1];//存储字符信息的类的数组
GetName()
{
sum=0;
n=0;
}
};
<4>定义编码类:
classCodeNode//编码类
{
public:
charch;//存储字符
charsave_code[max1];//存储编码
};
<5>主要功能实现类:
classFunction
{
public:
GetNameL;
intfn;//定义哈夫曼数组大小
ElementHuffmanT[max3];//哈夫曼数组
CodeNodeCode[max1];//字符编码数组
Function()
{
fn=0;
}
};
3、主要功能界面:
1、主界面:
2、读取文章并对字符编码:
3、哈弗曼编码信息:
4、文章编码:
5、文章译码:
6、错误处理:
4、总结(课设心得体会):
三周的课程设计结束了,在这次的课程设计中不仅检验了我所学习的知识,也培养了我如何去把握一件事情,如何去做一件事情,又如何完成一件事情。
在设计过程中,与同学分工设计,和同学们相互探讨,相互学习,相互监督。
学会了合作,学会了运筹帷幄,学会了宽容,学会了理解,也学会了做人与处世。
课程设计是我们专业课程知识综合应用的实践训练,着是我们迈向社会,从事职业工作前一个必不少的过程.”千里之行始于足下”,通过这次课程设计,我深深体会到这句千古名言的真正含义.我今天认真的进行课程设计,学会脚踏实地迈开这一步,就是为明天能稳健地在社会大潮中奔跑打下坚实的基础.通过这次课程设计,本人在多方面都有所提高。
在这次设计过程中,体现出自己单独设计模具的能力以及综合运用知识的能力,体会了学以致用、突出自己劳动成果的喜悦心情,从中发现自己平时学习的不足和薄弱环节,从而加以弥补。
六、附录(源代码):
#include
#include
#include
#include
#definemax1150
#definemax250
#definemax3256
usingnamespacestd;
classElement//结点类
{
public:
charname;//字符名
intweight;//字符权值
intlchild;//左孩子
intrchild;//右孩子
intparent;//父结点
Element()
{
weight=0;
lchild=-1;
rchild=-1;
parent=-1;
}
~Element(){}
};
classCodeNode//编码类
{
public:
charch;//存储字符
charsave_code[max1];//存储编码
};
className//字符类
{
public:
charpname;//字符名
intnum;//字符出现的次数
doublelweight;//字符的权值
Name()
{
num=0;
lweight=0;
}
~Name(){}
};
classGetName//关于字符类
{
public:
charfile_name[max2];//文件名
intn;//字符的种类
intsum;//字符的总数
Nameletter[max1];//存储字符信息的类的数组
GetName()
{
sum=0;
n=0;
}
voidGetWeight()//得到字符的权值
{
for(inti=0;i{
letter[i].lweight=(double)letter[i].num/sum;//出现的次数除总数得到权值
}
}
intReadLetter()
{
ifstreaminput;
cout<<"请输入文件名:
"<cin>>file_name;
input.open(file_name);//打开文件
if(input.fail())
{
cout<<"该文件不存在!
"<return0;
}
charch;
ch=input.get();
letter[0].pname=ch;
letter[0].num++;
sum++;
while(!
input.eof())//读取文件中的所有字符
{
inttag=0;
ch=input.get();
for(inti=0;i{
if(letter[i].pname==ch)
{
letter[i].num++;
sum++;
tag=1;
}
}
if(tag==0)
{
n++;
letter[n].pname=ch;
letter[n].num++;
sum++;
}
}
sum--;
input.close();
GetWeight();//得到字符权值
}
};
classFunction
{
public:
GetNameL;
intfn;//定义哈夫曼数组大小
ElementHuffmanT[max3];//哈夫曼数组
CodeNodeCode[max1];//字符编码数组
Function()
{
fn=0;
}
voidCharHuffmanTCoding()//编码功能实现
{
inti,f,c;
char*cd=newchar[L.n+1];//暂时存储编码的数组
intstart;//编码读取起始位置
cd[L.n]='\0';
for(i=0;i{
Code[i].ch=HuffmanT[i].name;//字符信息
start=L.n;//起始位置
c=i;
while((f=HuffmanT[c].parent)>=0)
{
if(HuffmanT[f].lchild==c)//如果为左孩子,为‘0’
{
cd[--start]='0';
}
else//如果为右孩子,为‘1’
{
cd[--start]='1';
}
c=f;
}
strcpy(Code[i].save_code,&cd[start]);//将结果存入对应的编码数组中
}
}
voidOutputHuffmanTCode()
{
cout<<"哈夫曼编码:
"<cout<<"——————————————————————"<cout<<"字符\t\t哈夫曼编码"<for(inti=0;i{
cout<<"——————————————————————"<cout<cout<cout<}
cout<<"——————————————————————"<}
voidInitHT()//哈夫曼初始化
{
L.ReadLetter();
fn=(L.n)*2-1;
for(inti=0;i{
if(i{
HuffmanT[i].name=L.letter[i].pname;
HuffmanT[i].weight=L.letter[i].lweight;
}
}
}
voidSelect_2Min(intm,int&p1,int&p2)//选择最小的两个节点
{
inti;
doublem1,m2;
m1=m2=1;
p1=p2=-1;
for(i=0;i{
if(HuffmanT[i].parent==-1&&HuffmanT[i].weight{
m2=m1;
p2=p1;
m1=HuffmanT[i].weight;
p1=i;
}
elseif(HuffmanT[i].parent==-1&&HuffmanT[i].weight{
m2=HuffmanT[i].weight;
p2=i;
}
}
}
voidCreatHT()//建立哈夫曼树//核心
{
inti,p1,p2;
InitHT();
for(i=L.n;i{
Select_2Min(i,p1,p2);
HuffmanT[p1].parent=HuffmanT[p2].parent=i;
HuffmanT[i].weight=HuffmanT[p1].weight+HuffmanT[p2].weight;
HuffmanT[i].lchild=p1;
HuffmanT[i].rchild=p2;
}
}
intOutArticleCode()//显示文章编码
{
ifstreaminput;
input.open(L.file_name);
if(input.fail())
{
cout<<"文件不存在!
"<return0;
}
charch;
cout<<"文章编码如下:
"<while(!
input.eof())
{
ch=input.get();
for(inti=0;i{
if(Code[i].ch==ch)
cout<}
}
cout<input.close();
}
intSaveArticleCode()//保存文章编码
{
ofstreamoutput;
ifstreaminput;
charnamef1[max2];
input.open(L.file_name);
if(input.fail())
{
cout<<"该文件不存在!
"<return0;
}
cout<<"请输入保存文章编码的文件名:
"<cin>>namef1;
output.open(namef1);
charch;
while(!
input.eof())
{
ch=input.get();
for(inti=0;i{
if(Code[i].ch==ch)
{
for(intj=0;j{
output.put(Code[i].save_code[j]);
}
}
}
}
input.close();
output.close();
cout<<"保存完毕!
"<}
intOutTransCode()//文章译码操作
{
ifstreaminput;
charnamef[max2];
cout<<"请输入保存文章编码的文件名:
"<cin>>namef;
input.open(namef);
if(input.fail())
{
cout<<"该文件不存在!
"<return0;
}
charch;
ch=input.get();
intc=2*L.n-2;
while(!
input.eof())
{
if(ch=='0')//遇0搜索左子树
{
if(HuffmanT[c].lchild>=0){
c=HuffmanT[c].lchild;
}
if(HuffmanT[c].lchild==-1)//判断是否到叶子
{
cout<c=2*L.n-2;//返回根节点
}
}
if(ch=='1')//遇1搜索右子树
{
if(HuffmanT[c].rchild>=0)
{
c=HuffmanT[c].rchild;
}
if(HuffmanT[c].rchild==-1)//判断是否到叶子
{
cout<c=2*L.n-2;//返回根节点
}
}
ch=input.get();
}
cout<input.close();
}
intSaveTransCode()//保存文章译码
{
ofstreamoutput;
ifstreaminput;
charnamef[max2];
charnamef1[max2];
cout<<"请输入文章编码所在的文件名:
"<cin>>namef;
input.open(namef);
if(input.fail())
{
cout<<"该文件不存在!
"<return0;
}
cout<<"请输入保存文章译码的文件名:
"<cin>>namef1;
output.open(namef1);
charch;
ch=input.get();
intc=2*L.n-2;
while(!
input.eof())
{
if(ch=='0')
{
if(HuffmanT[c].lchild>=0)
{
c=HuffmanT[c].lchild;
}
if(HuffmanT[c].lchild==-1)
{
output.put(HuffmanT[c].name);
c=2*L.n-2;
}
}
if(ch=='1')
{
if(HuffmanT[c].rchild>=0)
{
c=HuffmanT[c].rchild;
}
if(HuffmanT[c].rchild==-1){
output.put(HuffmanT[c].name);
c=2*L.n-2;
}
}
ch=input.get();
}
input.close();
output.close();
cout<<"保存完毕!
"<}
};
intmain()
{
Function*a=newFunction;
while
(1)//主界面显示
{
cout<<"************************************"<cout<<"*******欢迎进入编/译码系统**********"<cout<<"************************************"<cout<cout<<"*******功能如下:
*******************"<cout<<"*******1.读取文章并对字符编码*******"<cout<<"*******2.哈夫曼编码信息*************"<cout<<"*******3.文章编码*******************"<cout<<"*******4.文章译码*******************"<cout<<"*******5.退出程序*******************"<cout<charch;
cout<<"====>>请选择功能:
";
cin>>ch;
switch(ch)
{
case'1':
//读取文章并对字符编码
{
deletea;
a=newFunction;
system("cls");
a->CreatHT();
a->CharHuffmanTCoding();
cout<<"操作完毕!
"<system("pause");
system("cls");
break;
}
case'