北邮数据结构实验三-哈夫曼树
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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结点字符的权重赋为是左右孩