欢迎光临汇报书
当前位置: > 报告范文 > 综合报告 > 报告范文

北邮数据结构实验报告

发布时间:2026-05-23 18:05:15 浏览次数:25 格式:DOC

导语:还在为哈夫曼编解码器实现发愁?这篇范文值得一读。全文约2100字,14分钟即可掌握。内容核心:用了类封装和链表存储,代码模块化强,专业感足;高通过率的关键是每个函数都有注释和复杂度分析,还附了流程图和打印效果,模板可以直接套。

报告信息

适用对象:计算机相关专业本科生,刚学二叉树和哈夫曼编码的学生。

使用场合:高校计算机专业实验报告,适用于数据结构课程的编程作业提交,北邮这类工科院校的期中/期末实验。

核心内容:用了类封装和链表存储,代码模块化强,专业感足;高通过率的关键是每个函数都有注释和复杂度分析,还附了流程图和打印效果,模板可以直接套。

内容体量:2100字
  阅读时长:14分钟

报告正文

北邮数据结构实验报告

北京邮电大学信息与通信工程学院

____级数据结构实验报告

实验名称: 实验三哈夫曼编/解码器的实现

学生姓名:陈聪捷

日 期: ____年11月28日

1.实验要求

一、实验目的:

了解哈夫曼树的思想和相关概念;

二、实验内容:

利用二叉树结构实现哈夫曼编/解码器

1.初始化:能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立哈夫曼树。

2.建立编码表:利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。

3.编码:根据编码表对输入的字符串进行编码,并将编码后的字符串输出。

4.译码:利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。

5.打印:以直观的方式打印哈夫曼树。

6.计算输入的字符串编码前和编码后的长度,并进行分析,讨论哈夫曼编码的压缩效果。

7.用户界面可以设计成“菜单”方式,能进行交互,根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码。

2. 程序分析

2.1 存储结构

二叉树

template

class bitree

{

public:

bitree; //构造函数,其前序序列由键盘输入

~bitree(void); //析构函数

binode_ getroot; //获得指向根结点的指针

protected:

binode _root; //指向根结点的头指针

};

//声明类bitree及定义结构binode

data:

二叉树是由一个根结点和两棵互不相交的左右子树构成

哈夫曼树类的数据域,继承节点类型为int的二叉树 class huffmantree:public bitree

data:

hcode_ hcodetable;//编码表

int tsize; //编码表中的总字符数

二叉树的节点结构

struct binode //二叉树的结点结构 {

t data; //记录数据

t lchild; //左孩子

t rchild; //右孩子

t parent; //双亲

编码表的节点结构

struct hcode

char data; //编码表中的字符

char code[100]; //该字符对应的编码

待编码字符串由键盘输入,输入时用链表存储,链表节点为 struct node

char character; //输入的字符

unsigned int count;//该字符的权值

bool used; //建立树的时候该字符是否使用过

node_ ne_t; //保存下一个节点的地址

示意图:

2.2 关键算法分析

1.初始化函数(void huffmantree::init(string input))

算法伪代码:

1.初始化链表的头结点

2.获得输入字符串的第一个字符,并将其插入到链表尾部,n=1(n记录的是链表

中字符的个数)

3.从字符串第2个字符开始,逐个取出字符串中的字符

3.1 将当前取出的字符与链表中已经存在的字符逐个比较,如果当前取出

的字符与链表中已经存在的某个字符相同,则链表中该字符的权值加1。

3.2 如果当前取出的字符与链表中已经存在的字符都不相同,则将其加入

到链表尾部,同时n

4.tsize=n(tsize记录链表中字符总数,即哈夫曼树中叶子节点总数)

5.创建哈夫曼树

6.销毁链表

源代码:

void huffmantree::init(string input)

node _front=new node; //初始化链表的头结点

if(!front)

throw e_ception(堆空间用尽);

front->;;;ne_t=null;

front->;;;character=null;

front->;;;count=0;

node _pfront=front;

char ch=input[0]; //获得第一个字符

node_ new1=new node;

if(!new1)

new1->;;;character=ch; //将第一个字符插入链表

new1->;;;count=1;

new1->;;;ne_t=pfront->;;;ne_t;

pfront->;;;ne_t=new1;

bool replace=0; //判断在已经写入链表的字符中是否有与当前读出的字符相同的字符 int n=1; //统计链表中字符个数

for(int i=1;i

ch=input[i]; //获得第i个字符

do

pfront=pfront->;;;ne_t;

if((int)pfront->;;;character == (int)ch) //如果在链表中有与当前字符相同的字符,

该字符权值加1

pfront->;;;count ;

replace=1;

break;

}

}while(pfront->;;;ne_t);

if(!replace) //如果在链表中没找到与当前字符相同的字符,则将该字符作为新成 员插入链表

node_ new=new node;

if(!new)

new->;;;character=ch;

new->;;;count=1;

new->;;;ne_t=pfront->;;;ne_t;

pfront->;;;ne_t=new;

n ;

}

pfront=front; //重置pfront和replace变量为默认值 replace=0;

}

tsize=n; //tsize记录的是编码表中字符个数

createhtree(front,n); //创建哈夫曼树

pfront=front;

while(pfront) //销毁整个链表

{

front=pfront;

pfront=pfront->;;;ne_t;

front;

}

时间复杂度:

若输入的字符串长度为n,则时间复杂度为o(n)

2.创建哈夫曼树(void huffmantree::createcodetable(node _p))

算法伪代码:

1. 创建一个长度为2_tsize-1的三叉链表

2. 将存储字符及其权值的链表中的字符逐个写入三叉链表的前tsize个结点

的data域,并将对应结点的孩子域和双亲域赋为空

3. 从三叉链表的第tsize个结点开始,i=tsize

3.1 从存储字符及其权值的链表中取出两个权值最小的结点_,y,记录其

下标_,y。

3.2 将下标为_和y的哈夫曼树的结点的双亲设置为第i个结点

3.3 将下标为_的结点设置为i结点的左孩子,将下标为y的结点设置为

i结点的右孩子,i结点的权值为_结点的权值加上y结点的权值,i

结点的双亲设置为空

4. 根据哈夫曼树创建编码表

源代码:

void huffmantree::createhtree(node _p,int n)

{

root= new binode[2_n-1]; //初始化哈夫曼树

node _front=p->;;;ne_t;

if(n==0)

throw e_ception(没有输入字符);

for(int i=0;i

root[i].data=front->;;;count;

root[i].lchild=-1;

root[i].rchild=-1;

root[i].parent=-1;

front=front->;;;ne_t;

}

front=p;

int new1,new2;

for(i=n;i<2_n-1;i )

{

selectmin(new1,new2,0,i); //从0~i中选出两个权值最小的结点

root[new1].parent=root[new2].parent=i; //用两个权值最小的结点生成新结点,

新节点为其双亲

root[i].data=root[new1].data root[new2].data;//新结点的权值为其孩子的权值的和 root[i].lchild=new1;

root[i].rchild=new2;

root[i].parent=-1;

}

createcodetable(p); //创建编码表

}

时间复杂度:

在选取两个权值最小的结点的函数中要遍历链表,时间复杂度为o(n),故该函数

的时间复杂度为o(n^2)

3.创建编码表(void huffmantree::createcodetable(node _p))

算法伪代码:

1.初始化编码表

2.初始化一个指针,从链表的头结点开始,遍历整个链表

2.1 将链表中指针当前所指的结点包含的字符写入编码表中

2.2 得到该结点对应的哈夫曼树的叶子结点及其双亲

2.3 如果哈夫曼树只有一个叶子结点,将其字符对应编码设置为0

2.4 如果不止一个叶子结点,从当前叶子结点开始判断

2.4.1 如果当前叶子结点是其双亲的左孩子,则其对应的编码为0,否

则为1

2.4.2 child指针指向叶子结点的双亲,parent指针指向child指针的双亲,

重复2.4.1的操作

2.5 将已完成的编码倒序

2.6 取得链表中的下一个字符

3.输出编码表

源代码:

void huffmantree::createcodetable(node _p)

{

hcodetable=new hcode[tsize]; //初始化编码表

node _front=p->;;;ne_t;

for(int i=0;i

{

hcodetable[i].data=front->;;;character; //将第i个字符写入编码表

int child=i; //得到第i个字符对应的叶子节点

int parent=root[i].parent; //得到第i个字符对应的叶子节点的双亲

int k=0;

if(tsize==1) //如果文本中只有一种字符,它的.编码为0

{

hcodetable[i].code[k]=;

k ;

}

while(parent!=-1) //从第i个字符对应的叶子节点开始,寻找它到根结点的路径

{

if(child==root[parent].lchild) //如果当前结点为双亲的左孩子,则编码为0,

否则编码为1

hcodetable[i].code[k]=;

else

hcodetable[i].code[k]=1;

k ;

child=parent;

parent=root[child].parent;

}

hcodetable[i].code[k]=;

reverse(hcodetable[i].code); //将编码逆置

front=front->;;;ne_t; //得到下一个字符

}

cout<

for(i=0;i

{

cout<

parent=root[parent].lchild;

else //编码为1则寻找右孩子

parent=root[parent].rchild;

i ;

}

if(tsize==1) //如果编码表只有一个字符,则根结点即为叶子结点 i ;

d.append(1,hcodetable[parent].data);//将叶子节点对应的字符追加到解码串中 }

cout<

}

时间复杂度:

设待解码串长度为n,则复杂度为o(n)

8. 计算哈夫曼编码的压缩比(void huffmantree::calculate(string s1,string s2)) 算法伪代码:

1. 获得编码前字符串的长度,即其占用的字节数

2. 获得编码后的字符串的长度,将其除以8然后向上取整,得到其占用的字

节数

3. 压缩比将两个相除

源代码:

void huffmantree::calculate(string s1,string s2)

{

int cal1=s1.length;

int cal2=s2.length;

cal2=ceill((float)cal2/8); //将编码串的比特数转化为字节数 cout<

cout<

cout<

}

时间复杂度:

o(1)

9. 打印哈夫曼树(void huffmantree::printtree(int treenode,int layer) ) 算法伪代码:

1. 如果待打印结点为空,则返回

2. 递归调用函数打印当前结点的右子树

3. 根据当前结点所在的层次确定其前面要输出多少空格,先输出空格,在打

印当前结点的权值

4. 递归调用函数打印当前结点的左子树

源代码:

void huffmantree::printtree(int treenode,int layer)

{

if(treenode==-1) //如果待打印结点为空,则返回 return;

else

{

printtree(root[treenode].rchild,layer 1); //先打印该结点的右子树,layer记录

的是该结点所在的层次

for(int i=0;i

空格

cout<< ;

cout<

printtree(root[treenode].lchild,layer 1); //打印该结点的左子树

}

}

时间复杂度:

中序遍历哈夫曼树,复杂度为o(n)

10. 菜单函数(void huffmantree::menu)

算法伪代码:

1. 逐一读取键盘缓存区中的字符,并将它们逐一追加到记录输入字符串的

string变量中,直到读到回车输入符为止

2. 删除string变量末尾的回车输入符

3.利用string变量创建哈夫曼树,初始化编码表。

4. 直观打印哈夫曼树

5. 对输入的字符串进行编码

6. 对编码后的字符串进行解码

7. 计算编码前后的压缩比并输出

源代码:

void huffmantree::menu

{

cout<

string input;

char letter;

do //将字符逐个读入input变量中

{

letter=cin.get;

input.append(1,letter);

}while(letter!= );

input.erase(input.length-1,1); //去掉input末尾的回车符

init(input); //根据输入的字符串创建哈夫曼树及其编码表 cout<

printtree(2_tsize-1-1,1); //打印哈夫曼树

cout<< << ;

string d1,d2;

cout<

encode(input,d1); //编码并打印编码串

cout<

decode(d1,d2); //解码并打印解码串

cout<

calculate(input,d1); //计算编码前后的压缩比

}

2.3 其他

1.由于题目要求能输入任意长的字符串,所以本程序采用了string变量来记录输入

的字符串,并采用string类的类成员函数来完成各项任务

2.打印哈夫曼树时采用了递归函数,且采用了凹凸表的形式打印哈夫曼树。

3.为了输入空格,输入时采取逐个字符输入的方式

3. 程序运行结果

主函数流程图:

运行结果:

各函数运行正常,没有出现bug

4. 总结

经过这次实验,我了解了哈夫曼树的创建过程,了解了一种不等长编码的方法,用设断点调试的方法更加熟练,同时熟悉了stl中string类型的用法,对c 更加熟悉

报告怎么写

有固定标题、学生信息、实验目的、内容、代码分析、运行结果和总结;层次分明,分块明确,像模板一样填空就行。

北邮数据结构实验报告

北邮数据结构实验报告,别再为代码调试抓狂、为流程图发愁啦!这份报告框架清晰、逻辑性扎实,覆盖常见实验难点,为您明确思路、少走弯路。参阅时顺便就能套用,排版规范还不失个性,交作业前翻一翻,心里立马有底。
推荐度: Star Star Star Star Star
点击下载文档文档为doc格式

延伸阅读

相关分类 内容标题 内容介绍
数据结构实习报告 数据结构实习报告 适配人群:计算机专业学生、高校实验指导教师 [详情]
数据结构报告 数据结构报告 数据结构实践报告分析一、需求分析1、 程序所实现的功能;2、 程序的输入,包含输入的数据格式和说明;3、 程序的输出,程序输出的形式;4、 测试数据,如果程序输... [详情]
数据结构实验报告 数据结构实验报告 实验五一.实验内容:实现哈夫曼编码的生成算法。二.实验目的:1、使学生熟练掌握哈夫曼树的生成算法。2、熟练掌握哈夫曼编码的方法。三.问题描述:... [详情]

相关数据结构范文

  • 数据结构报告
  • 数据结构报告 1148人关注

    数据结构实践报告分析一、需求分析1、 程序所实现的功能;2、 程序的输入,包含输入的数据格式和说明;3、 程序的输出,程序输出的形式;4、 测试数据,如果程序输 ...[更多]

  • 数据结构实验报告
  • 数据结构实验报告 1119人关注

    数据结构实验报告 实验五一.实验内容:实现哈夫曼编码的生成算法。二.实验目的:1、使学生熟练掌握哈夫曼树的生成算法。2、熟练掌握哈夫曼编码的方法。三.问题描述: ...[更多]

报告范文热门信息