北邮 数据结构 哈夫曼树报告.docx

上传人:b****6 文档编号:7513644 上传时间:2023-01-24 格式:DOCX 页数:11 大小:38.54KB
下载 相关 举报
北邮 数据结构 哈夫曼树报告.docx_第1页
第1页 / 共11页
北邮 数据结构 哈夫曼树报告.docx_第2页
第2页 / 共11页
北邮 数据结构 哈夫曼树报告.docx_第3页
第3页 / 共11页
北邮 数据结构 哈夫曼树报告.docx_第4页
第4页 / 共11页
北邮 数据结构 哈夫曼树报告.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

北邮 数据结构 哈夫曼树报告.docx

《北邮 数据结构 哈夫曼树报告.docx》由会员分享,可在线阅读,更多相关《北邮 数据结构 哈夫曼树报告.docx(11页珍藏版)》请在冰豆网上搜索。

北邮 数据结构 哈夫曼树报告.docx

北邮数据结构哈夫曼树报告

 

数据结构

 

实验名称:

哈夫曼树

学生:

袁普

班级:

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(s1.c_str());将编码字符串转化为char

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的优越性。

还有就是编码时要注意数组的大小。

再者就是有问题时可以试着去网上查询答案。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工作范文 > 制度规范

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1