北邮数据结构实验三-哈夫曼树

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

数据结构实验报告

实验名称:实验三——树

学生姓名:

班级:

班内序号:

学号:

日期:

1 实验目的

通过选择下面两个题目之一进行实现,掌握如下内容:

➢掌握二叉树基本操作的实现方法

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

➢学习使用二叉树解决实际问题的能力

实验内容:

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

基本要求:

1、初始化(Init):能够对输入的任意长度的字符串s进行统计,统计每个

字符的频度,并建立哈夫曼树

2、建立编码表(CreateTable):利用已经建好的哈夫曼树进行编码,并将每

个字符的编码输出。

3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的

字符串输出。

4、译码(Decoding):利用已经建好的哈夫曼树对编码后的字符串进行译

码,并输出译码结果。

5、打印(Print):以直观的方式打印哈夫曼树(选作)

6、计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫曼

编码的压缩效果。(选作)

7、可采用二进制编码方式(选作)

测试数据:

I love data Structure, I love Computer。I will try my best to study data

Structure.

2 程序分析

2.1存储结构:

三叉树:

class Huffman

{

private:

HNode*HTree;//哈夫曼树结点

HCode*HCodeTable;//哈夫曼编码表

char b[1000];//记录所有输入内容被编码后的结果

char c[127];

char letter[1000];//输入内容的保存

void SelectMin(int &x,int &y,int k);//求最小权重的字符node*count;//计算各个字符出现次数

int n;//输入字符的种类(个数)

int l;

public:

Huffman();

void CreateHTree();//创建哈夫曼树

void CreateCodeTable();//创建哈夫曼编码表

void Encode();//编码

void Decode();//解码

};

结点结构为如下所示:

三叉树的节点结构:

struct HNode//哈夫曼树结点的结构体

{ int weight;//结点权值

int parent;//双亲指针

int lchild;//左孩子指针

int rchild;//右孩子指针

char data;//字符

};

示意图为:

编码表节点结构:

struct HCode//编码表结构体

{

char data;//字符

char code[100];//编码内容

};

基本结构体记录字符和出现次数:

struct node

{

int num;

char data;

};

2.关键算法分析

(1).初始化:

伪代码:

1.输入需要编译的文本内容

2.将输入的内容保存到动态建立的node型数组count中

3.统计出现的字符种类的数目,并且保存到private型变量n

Huffman::Huffman()//将输入数据保存到Huffman类中

{

l=0;

n=0;

count=new node[127];

cout<<"请输入需要编译压缩的内容"<

cin.getline(letter,200,'\n');

for(int j=0;j<127;j++) //一个号码代表一种字符

{

count[j].num=0;

}

while(letter[l]!='\0')//在结束之前,每输入一个字符,则对应字符的数目则自增1 {

++count[letter[l]].num;

count[letter[l]].data=letter[l];

++l;

}

for(int k=0;k<127;k++) {

if(count[k].num>0)

{n++;}//在某个字符出现此书num不为0时,n自增1,最终n为出现的字符种类数目

}

其时间复杂度为O(n)

(2).创建哈夫曼树(void HuffmanTree::CreateCodeTable(Node *p))

算法伪代码:

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

2.将存储字符及其权值的链表中的字符逐个写入三叉链表的前n个结点的data域,并将对

应结点的孩子域和双亲域赋为空

3.从三叉链表的第n个结点开始,

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

下标x,y。

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

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

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

结点的双亲设置为空

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

源代码为:

void Huffman::CreateHTree()

{

l=0;

HTree=new HNode[2*n-1];//建立含有n种字符的哈夫曼树只需要2*n-1个结点即可

for(int i=0;i

{

while (count[l].num==0)//如果count内的权重为0,即该字符没有出现,则跳过,i 自增继续寻找出现过的字符

{l++;}

HTree[i].weight=count[l].num;//将count里统计的次数传入哈夫曼树的节点中,作为字符权重

HTree[i].lchild=-1;

HTree[i].rchild=-1;

HTree[i].parent=-1;//将左右孩子结点和父节点都置空

HTree[i].data=count[l].data;//将count内的有效字符传入哈夫曼树的结点

l++;

}

int x=-1,y=-1;

for(int i=n;i<2*n-1;i++)//开始建立哈夫曼树

{

SelectMin(x,y,i);//挑选三者中的权重较小的两个

HTree[x].parent=HTree[y].parent=i;//令较小的x、y为孩子节点,该两个结点的父节点是i

HTree[i].weight=HTree[x].weight+HTree[y].weight;//i结点字符的权重赋为是左右孩

相关文档
最新文档