北邮 数据结构 哈夫曼树报告.docx
- 文档编号:28569653
- 上传时间:2023-07-19
- 格式:DOCX
- 页数:13
- 大小:38.74KB
北邮 数据结构 哈夫曼树报告.docx
《北邮 数据结构 哈夫曼树报告.docx》由会员分享,可在线阅读,更多相关《北邮 数据结构 哈夫曼树报告.docx(13页珍藏版)》请在冰豆网上搜索。
北邮数据结构哈夫曼树报告
数据结构
实
验
报
告
实验名称:
哈夫曼树
学生姓名:
袁普
班级:
2013211125班
班内序号:
14号
学号:
2013210681
日期:
2014年12月
1.
实验目的和内容
利用二叉树结构实现哈夫曼编/解码器。
基本要求:
1、初始化(Init):
能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,
并建立哈夫曼树
2、建立编码表(CreateTable):
利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。
3、编码(Encoding):
根据编码表对输入的字符串进行编码,并将编码后的字符串输
出。
4、译码(Decoding):
利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出
译码结果。
5、打印(Print):
以直观的方式打印哈夫曼树(选作)
6、计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫曼编码的压
缩效果。
7、可采用二进制编码方式(选作)
测试数据:
IlovedataStructure,IloveComputer。
IwilltrymybesttostudydataStructure.
提示:
1、用户界面可以设计为“菜单”方式:
能够进行交互。
2、根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码
2.程序分析
2.1存储结构
用struct结构类型来实现存储
树的结点类型
structHNode
{
intweight;//权值
intparent;//父节点
intlchild;//左孩子
intrchild;//右孩子
};
structHCode//实现编码的结构类型
{
chardata;//被编码的字符
charcode[100];//字符对应的哈夫曼编码
};
2.2程序流程
输入字符串
统计出现的字符种类和次数,构建权值数组,初始化树结点与编码表
根据哈夫曼构建规则构建哈夫曼树,根据编码规则对出现字符进行编码,构建编码表
将输入的字符挨个编码
对编码后的字符进行解码
分析存储大小
2.3关键算法分析
算法1:
voidHuffman:
:
Count()
[1]算法功能:
对出现字符的和出现字符的统计,构建权值结点,初始化编码表
[2]算法基本思想:
对输入字符一个一个的统计,并统计出现次数,构建权值数组,
[3]算法空间、时间复杂度分析:
空间复杂度O
(1),要遍历一遍字符串,时间复杂度O(n)
[4]代码逻辑:
leaf=0;//初始化叶子节点个数
inti,j=0;
ints[128]={0};用于存储出现的字符
for(i=0;str[i]!
='\0';i++)遍历输入的字符串
s[(int)str[i]]++;统计每个字符出现次数
for(i=0;i<128;i++)
if(s[i]!
=0)
{
data[j]=(char)i;给编码表的字符赋值
weight[j]=s[i];构建权值数组
j++;
}
leaf=j;//叶子节点个数即字符个数
for(i=0;i cout< "< 算法2: voidInit(); [1]算法功能: 构建哈弗曼树 [2]算法基本思想: 根据哈夫曼树构建要求,选取权值最小的两个结点结合,新结点加入数组,再继续选取最小的两个结点继续构建。 [3]算法空间、时间复杂度分析: 取决于叶子节点个数,时间复杂度O(n),空间复杂度O (1) [4]代码逻辑 HTree=newHNode[2*leaf-1];n2=n0-1,一共需要2n-1个结点空间 for(inti=0;i { HTree[i].weight=weight[i];给每个结点附权值 HTree[i].lchild=-1;初始化左右孩子和父节点,都为-1 HTree[i].rchild=-1; HTree[i].parent=-1; } intx,y;//用于记录两个最小权值 for(inti=leaf;i<2*leaf-1;i++) { Selectmin(HTree,i,x,y);选出两个最小权值的结点 HTree[x].parent=i;父节点设置为新建立的结点 HTree[y].parent=i; HTree[i].weight=HTree[x].weight+HTree[y].weight;父节点权值为两个相加 HTree[i].lchild=x;使父节点指向这两个孩子结点 HTree[i].rchild=y; HTree[i].parent=-1;父节点的父节点设为-1 } 算法3: voidSelectmin(HNode*hTree,intn,int&i1,int&i2); [1]算法功能: 从现有的结点中选择出两个最小的结点,返回其位置 [2]算法基本思想: 先选出两个没有构建的结点,然后向后依次比较,筛选出最小的两个结点 [3]算法空间、时间复杂度分析: 空间复杂度O (1),要遍历所有结点,时间复杂度O(N) [4]代码逻辑 inti; for(i=0;i { if(hTree[i].parent==-1)//父节点不是-1意味着这个结点还没有被选择过 { i1=i;记录结点位置 break; } } i++;//执行一遍for循环就加1,意为下次查找从当前位置开始查找 for(;i { if(hTree[i].parent==-1) { i2=i;记录第二个没选择过的结点编号 break; } } if(hTree[i1].weight>hTree[i2].weight)进行比较,使I1为最小的,I2为第二小的 { intj=0; j=i2; i2=i1; i1=j; } i++; for(;i { if(hTree[i].parent==-1&&hTree[i].weight { i2=i1;使I2=I1I1=新结点 i1=i; } elseif(hTree[i].parent==-1&&hTree[i].weight {I1《新结点《I2,使I2为新节点 i2=i; } } 算法4: voidCreateTable(); [1]算法功能: 对出现的字符进行编码 [2]算法基本思想: 根据字符在哈夫曼树中的位置,从下到上编码,是左孩子编0,右孩子编1 [3]算法空间、时间复杂度分析: 空间复杂度O (1),要遍历data数组,时间复杂度0(N) [4]代码逻辑 HCodeTable=newHCode[leaf];新建编码结点,个数为叶子节点个数 for(inti=0;i { HCodeTable[i].data=data[i]; intchild=i;初始化要编码的结点的位置 intparent=HTree[i].parent;初始化父结点 intk=0;//统计编码个数 while(parent! =-1) { if(child==HTree[parent].lchild) HCodeTable[i].code[k]='0';//左孩子标‘0’ else HCodeTable[i].code[k]='1';//右孩子标‘1’ k++; child=parent;孩子结点上移 parent=HTree[child].parent;父节点也上移 } HCodeTable[i].code[k]='\0';//将编码反向 charcode[100]; for(intu=0;u code[u]=HCodeTable[i].code[k-u-1]; for(intu=0;u HCodeTable[i].code[u]=code[u]; cout< "; cout< length3[i]=k;//每一个字符编码的长度,为求编码总长度做准备 } 算法5: voidEncoding(); [1]算法功能: 对输入的字符串进行编码 [2]算法基本思想: 找到每个字符对应的编码,将编码按顺序输出 [3]算法空间、时间复杂度分析: 空间复杂度O (1),时间复杂度0(n) [4]代码逻辑 cout< "< for(inti=0;str[i]! ='\0';i++)遍历输入的每一个字符 { for(intj=0;j if(str[i]==HCodeTable[j].data)找到字符对应的编码 {s1=s1+HCodeTable[j].code;将所有编码按顺序加起来 cout< } } cout< 算法6: voidDecoding(); [1]算法功能: 对编码串进行解码 [2]算法基本思想: 找到每段编码对应的字符,输出字符 [3]算法空间、时间复杂度分析: 时间复杂度0(N),空间复杂度0 (1) [4]代码逻辑(可用伪代码描述) cout<<"解码后的字符串为: "< char*s=const_cast while(*s! ='\0') { intparent=2*leaf-2;父节点为最后一个节点 while(HTree[parent].lchild! =-1)//还有左子树,不可能是叶子节点 { if(*s=='0')编码为0,为左孩子 parent=HTree[parent].lchild; else parent=HTree[parent].rchild;编码为1,为右孩子 s++; } cout< } cout< …… 注意分析程序的时间复杂度、内存申请和释放,以及算法思想的体现。 2.4其他 在此次试验中使用了类和STL中的string,使用string可以方便的将单个字符的编码加起来成为总的编码后的数值,再利用STL中的转化函数可以直接将string转化为char,方便进行解码工作。 总而言之,使用STL使得编码大大的简洁了。 3.程序运行结果分析 调试过程中遇到的问题主要是执行时有内存错误,检查后发现是数组有越界现象,这提醒我在编写时一定要仔细,特别是在for循环条件上一定要注意范围 总结 4.1实验的难点和关键点 首先在输入字符串时我发现直接用cin无法输入空格,在上网查询后找到了getline函数解决了这个问题。 然后还有就是如何存储编码后总的那个字符串,因为每一个字符编码的长度不定,无法用char数组来存储,于是用了string的相加函数来将所有编码加起来。 最后由于在解码时要用char数组,又上网查询到了string转化成char的函数解决了这个问题,实验难点也在于如何找到两个最小权值来构建哈夫曼树,寻找两个最小权值的思想主要是通过一个个的比较来找到最小值,而且注意形参要用引用。 4.2心得体会 通过此次实验我体会到了stl的优越性。 还有就是编码时要注意数组的大小。 再者就是有问题时可以试着去网上查询答案。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 北邮 数据结构 哈夫曼树报告 哈夫曼树 报告