北邮数据结构实验3哈夫曼编码

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

数据结构实验报告

实验名称:实验3——哈夫曼编码

学生姓名:

班级:

班内序号:

学号:

日期:2013年11月24日

1.实验要求

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

基本要求:

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

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

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

个字符的编码输出。

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

字符串输出。

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

码,并输出译码结果。

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

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

编码的压缩效果。

2. 程序分析

2.1存储结构:

struct HNode

{

char c;//存字符内容

int weight;

int lchild, rchild, parent;

};

struct HCode

{

char data;

char code[100];

}; //字符及其编码结构

class Huffman

{

private:

HNode* huffTree; //Huffman树

HCode* HCodeTable; //Huffman编码表

public:

Huffman(void);

void CreateHTree(int a[], int n); //创建huffman树

void CreateCodeTable(char b[], int n); //创建编码表

void Encode(char *s, string *d); //编码

void Decode(char *s, char *d); //解码

void differ(char *,int n);

char str2[100];//数组中不同的字符组成的串

int dif;//str2[]的大小

~Huffman(void);

};

结点结构为如下所示:

三叉树的节点结构:

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

{ int weight;//结点权值

int parent;//双亲指针

int lchild;//左孩子指针

int rchild;//右孩子指针

char data;//字符

};

示意图为:

int weight int parent int lchild int rchild Char c 编码表节点结构:

struct HCode//编码表结构体

{

char data;//字符

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

};

示意图为:

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

struct node

{

int num;

char data;

};

示意图为:

2.关键算法分析

(1).初始化:

伪代码:

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

2.将输入的内容保存到数组str1中

3.统计出现的字符数目,并且保存到变量count中

4.统计出现的不同的字符,存到str2中,将str2的大小存到dif中

时间复杂度O(n!)

(2).创建哈夫曼树

算法伪代码:

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.根据哈夫曼树创建编码表

时间复杂度O(n)

(3).创建编码表

算法伪代码:

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.输出编码表

时间复杂度O(n)

(4)选择两个最小权值的函数

算法伪代码:

1.从下标为i=0的开始遍历。前两次将x,y赋值为序号最小的两个结点的地址序

号。

2.开始进行比较:进行如下分类

对于任何不存在父节点的结点:

若x权值<=y权值

(1)且i权值>=y权值,则无疑i权值最大,为输出x、y为权值较小的两个故而x,y值不便;

(2)其余情况皆为x、i的权值是较小的两个,令y赋值为i,则保证x、y权值是最小的两个。

若y权值<=x权值

(1)且i权值>=x权值,则i权值是最大,x、y不变。

(2)其余情况皆为i、y权值最小,令x赋值为i,保证x、y序号结点的权值最小

3.完成如上循环,直至i=k则推出循环,第k个结点在树的位置已经确定

时间复杂度O(n)

(5). 将字符串倒序的函数(void HuffmanTree::Reverse(char *pch))

算法伪代码:

1.得到字符串的长度

2.初始化两个记录下标的变量,一个为字符串开头字符所在的下标i,另一个为字符串结尾字符所在的下标j

3.将下标为i和j的字符交换

4.i++,j - -

时间复杂度O(n)

(6).编码函数

算法伪代码:

1. 从开头的字符开始,逐一对a中的字符进行编码

2. 在编码表中查找与当前字符对应的字符

3.如果找到了与当前字符对应的编码表中的字符,将其编码追加到解码串的末

尾。

相关文档
最新文档