哈夫曼实验报告材料附代码Word格式文档下载.docx
《哈夫曼实验报告材料附代码Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《哈夫曼实验报告材料附代码Word格式文档下载.docx(24页珍藏版)》请在冰豆网上搜索。
}HNodeType;
HNodeTypeHNode[2*N-1];
(2)编码的类型定义描述如下:
#defineMAXBIT10
typedefstruct
{intbit[MAXBIT];
intstart;
}HCodeType;
HCodeTypeHCode[N];
2.各模块伪算法
(1)主函数
intmain()
{
do:
{
界面友好设计;
cout<
<
各个选项功能内容;
cin>
>
ch;
容错处理;
switch(ch)
{
case1:
.....
}
}while();
return0;
}
(2)系统初始化模块
voidcreate()//系统初始化
for(i=0;
i<
2*N-1;
i++)//数组HNode初始化
{};
从键盘接收字符;
N;
i++)
{cout<
"
输入字符"
endl;
HNode[i].data;
}
接收权值;
构造哈夫曼树;
N-1;
{找最小和次小两个权值;
将找出的两棵子树合并为一棵子数;
将已建好的哈夫曼树存入文件hfmtree.txt中;
调用哈夫曼编码子函数;
voidHaffmanCode()//对哈夫曼树进行编码
从hfmtree.txt文件中读出哈夫曼树的信息存入内存HNodeTypea[2*N-1];
求每个叶子结点的哈夫曼编码;
从叶节点回溯,回溯到根结点(parent==-1);
记录回溯路径;
打印出每个字符对应的密文;
将密文信息存入文件codefile.dat中;
(3)编码模块
voidHfmanCode()//对用户输入的字符串进行编码
提示输入信息;
接收用户输入的要编译的字符串;
cin>
s;
//从文件中读取哈夫曼编码信息
infile.open("
F:
\\codefile.dat"
ios:
:
in|ios:
binary);
//读文件
i++)//将文件中的数据读出放在temp[i]内
//从文件中读字节到指定的存储器区域。
infile.read((char*)&
temp[i],sizeof(temp[i]));
循环实现将用户输入的字符串转换成对应的密文,并保存;
将保存结果存入密文文件;
voidtranslate()//译码
从文件hfmtree.txt中读出哈夫曼信息到内存temp[2*N-1];
从密文文件中读取用户输入的字符串的密文信息到内存c;
追溯结点位置初始定位到根结点temp[2*N-2];
c.num;
{
if(c.code[i]==0)
在当前结点的左子树下追溯叶子结点;
找到叶子结点则输出字符,当前结点重新定位到根结点;
else
在当前结点的右子树下追溯叶子结点;
输出并保存明文;
(4)译码模块
(5)输出模块
voidprint()//将哈夫曼树以凹入表的形式输出
从文件hfmtree.tet中读出哈夫曼树信息存入内存temp[2*N-1];
定义h=1;
调用递归输出函数print_t(temp,temp[2*N-2],h);
voidprint_t(HNodeTypetemp[],HNodeTypeT,inth)
{
//叶子结点输出字符,分支结点输出权值
if(T.data!
='
\0'
)
cout<
T.data<
else
T.weight<
递归调用左子树;
递归调用右子树;
五、调试分析
1.调试过程中遇到的问题和对问题的解决方法
对文件的读写操作不熟悉,调试时,将已写入的文件不能读出,以至于后续操作无法实现,对此,我有翻看C++程序设计课本,了解关于文件操作的具体内容,明白二进制文件和文本文件的读写方式是有很大区别的,不可混淆操作。
另外,对于程序的输出阶段开始时出现了问题,递归调用没有分析清楚,递归思想是层次分明,逐层深入。
2.算法的时间复杂度
(1)创建模块O(N^3)
(2)编码模块O(N)
(3)译码模块O(n)其中n为用户输入的密文位数
(4)打印模块O(N)
六、使用说明及测试结果
用户根据提示信息,初次使用本系统时要首先选择创建选项来初始化系统,根据提示信息输入信息,存入文件,使得后续功能顺利实现。
非初次使用时,用户可根据自己的需求来选择功能选项,根据提示信息输入、获得所需信息。
测试:
1.令叶子结点个数N为4,权值集合为{1,3,5,7},字符集合为{A,B,C,D},且字符集与权值集合一一对应。
2.令叶子结点个数N为7,权值集合为{12,6,8,18,3,20,2},字符集合为{A,B,C,D,E,F,G},且字符集与权值集合一一对应。
3.自行选定一段英文文本,统计给出的字符集,实际统计字符的频度,建立哈夫曼树,构造哈夫曼编码,并实现其编码和译码。
字符串:
whilwitchhiwwppppp频率统计为
w
h
i
l
c
t
p
4
3
1
5
4.可实现多个编码文件共存以及容错处理
七、程序代码
#include<
iostream.h>
iomanip.h>
fstream.h>
string.h>
#defineN7//叶子结点的个数
#defineMAXBIT50//编码位数
#defineMaxvalue100//定义最大权值整数常量
//结点的类型定义描述如下:
chardata;
intweight;
//编码类型描述如下:
chars;
//密文格式类型
intcode[MAXBIT];
intnum;
}CD;
voidcreate();
voidHaffmanCode();
voidprint();
voidprint_t(HNodeTypetemp[],HNodeTypeT,inth);
voidtranslate();
voidHfmanCode();
charname[50][30];
//用来记录用户输入的密文文件
intfilenum=0;
inttextnum=0;
intmain()
charch;
inth=1;
HNodeType*pNode;
pNode=HNode;
do{
setw(60)<
"
---------欢迎进入系统!
--------------"
setw(50)<
1:
初始化编译系统"
endl<
setw(40)<
2:
编码"
3:
译码"
setw(48)<
4:
打印哈弗曼树"
5:
退出"
--------------------------------------"
请选择(0~5):
;
while(!
(ch<
5'
&
ch>
0'
))/*输入不在0到5之间无效*/
cout<
数据输入错误,请重新选择(0~7):
cin>
switch(ch)
case'
1'
create();
break;
//系统初始化,构造哈夫曼树
2'
HfmanCode();
//对哈夫曼树进行编码
3'
translate();
//译码
4'
print();
//将哈夫曼树以凹入表的形式输出
case'
}while(ch!
);
voidcreate()//模块一,系统初始化
fstreamoutfile;
inti,j;
intm1,m2,x1,x2;
HNode[i].data='
HNode[i].weight=0;
HNode[i].parent=-1;
HNode[i].lchild=-1;
HNode[i].rchild=-1;
分别输入"
N<
个叶子结点的字符。
//从键盘接收叶子节点的权值
个与字符对应的权值。
输入权值"
HNode[i].weight;
i++)//构造哈夫曼树
m1=m2=Maxvalue;
x1=x2=0;
for(j=0;
j<
N+i;
j++)//找最小和次小两个权值
if(HNode[j].parent==-1&
HNode[j].weight<
m1)
{
m2=m1;
x2=x1;
m1=HNode[j].weight;
x1=j;
}
else
if(HNode[j].parent==-1&
m2)
{
m2=HNode[j].weight;
x2=j;
}
//将找出的两棵子树合并为一棵子数
HNode[x1].parent=N+i;
HNode[x2].parent=N+i;
HNode[N+i].weight=HNode[x1].weight+HNode[x2].weight;
HNode[N+i].lchild=x1;
HNode[N+i].rchild=x2;
outfile.open("
\\hfmtree.txt"
out|ios:
//建立进行写入的文件
if(!
outfile)//没有创建成功则显示相应信息
hfmtree.txt文件不能打开"
return;
//将内存中从HNode[i]地址开始的sizeof(HNode[i])的内容写入文件中
outfile.write((char*)&
HNode[i],sizeof(HNode[i]));
哈夫曼树信息已存入文件hfmtree.tet中."
outfile.close();
//关闭文件
HaffmanCode();
//调用函数对哈夫曼树进行编码
voidHaffmanCode()//对哈夫曼树进行编码
fstreamoutfile,infile;
inti,j,c,p;
HCodeTypecd;
HNodeTypea[2*N-1];
infile)
hfmtree.dat文件不能打开"
i++)//将文件中的数据读出放在a[i]内
//从文件中读字节到指定的存储器区域。
infile.read((char*)&
a[i],sizeof(a[i]));
infile.close();
//求每个叶子结点的哈夫曼编码
cd.start=N-1;
c=i;
p=a[c].parent;
while(p!
=-1)
if(a[p].lchild==c)
cd.bit[cd.start]=0;
cd.bit[cd.start]=1;
cd.start--;
c=p;
p=a[c].parent;
字符对应密文:
//打印出每个字符对应的密文
a[i].data<
---"
for(j=cd.start+1;
j++)
//保存求出的每个叶节点的哈夫曼编码和编码的起始位
HCode[i].bit[j]=cd.bit[j];
cd.bit[j];
HCode[i].start=cd.start;
HCode[i].s=a[i].data;
codefile.dat文件不能打开"
//将内存中从HCode[i]地址开始的sizeof(HCode[i])的内容写入文件中
outfile.write((char*)&
HCode[i],sizeof(HCode[i]));
//关闭文件n
密文信息已存入文件codefile.dat中."
inti,h=1;
HNodeTypetemp[2*N-1];
fstreaminfile;
print_t(temp,temp[2*N-2],h);
inti;
for(i=1;
h;
if(T.lchild==-1)
print_t(temp,temp[T.lchild],h+1);
//递归遍历左子树
print_t(temp,temp[T.rchild],h+1);
//递归遍历右子树
chars[50]={'
};
inti,j,k,n=0,m;
CDc;
c.num=0;
fstreaminfile,outfile;
HCodeTypetemp[N];
输入字符串"
m=strlen(s);
输入要将密文存放的文件名"
name[filenum];
filenum++;
m;
if(s[i]==temp[j].s)
for(k=temp[j].start+1;
k<
k++)
cout<
temp[j].bit[k];
//输出
c.code[c.num]=temp[j].bit[k];
//将字符对应密文存入c中
c.num++;
//记录密文长度
n++;
if(n==30)//实现每行输出30个密文
{
cout<
n=0;
}
outfile.open(name[filenum-1],ios:
name[filenum-1]<
.dat文件不能打开"
//将内存中从c内容写入文件中
c,sizeof(c));
密文信息已存入文件"
.dat中."
HNodeTypetemp[2*N-1],q;
charch,r[50]={'
},tempname[30]={'
intn=0,t=0,i;
输入要译码的文件"
tempname;
filenum;
if(strcmp(tempname,name[i])==0)
break;
if(i==filenum)
密文文件中没有"
tempname<
文件"
infile.open(name[i],ios:
cout