哈夫曼树的建立

 

设计题目:

一、设计实验条件

    DevC++

二、设计任务及要求

1. 建立最优二叉树函数;

2. 建立函数输入二叉树,并输出其赫夫曼树;

3. 分析算法的时间复杂度,进行优化。

 

三、设计报告的内容

1. 设计题目与设计任务

    

设计题目:建立赫夫曼树。

设计任务:建立最优二叉树函数,并输出其赫夫曼树。实现赫夫曼树存储结构的初始化,建立赫夫曼树并打印。在此基础上对算法的时间复杂度进行分析并进行优化。

 

2. 前言(绪论)

    

在很多问题的处理过程中,需要进行大量的条件判断,这些判断结构的设计直接影响着程序的执行效率。因此,我们需要寻找一种最佳判定树,即赫夫曼树,来高效地存储、处理数据。本课程设计主要进行赫夫曼树的建立,通过此设计充分理解赫夫曼树的原理,同时也为赫夫曼编码奠定基础。

赫夫曼树的建立是赫夫曼编码的前提,赫夫曼编码可以起到数据压缩的作用,提高程序的执行效率。   

 

3. 设计主体

3.1需求分析

1.任务:

本程序主要通过用户输入二叉树各个节点的权值,然后输出赫夫曼树。

2.功能模块:

  哈夫曼树的建立_第1张图片

3.流程图:

      哈夫曼树的建立_第2张图片

4.输入输出

输入形式:数字(整数)

       输入范围:节点数:1到20;权值:int范围

      输出形式:数字,括号,逗号。

 

    5.功能:

 

输出赫夫曼树,能够显示每个节点的左子树,右子树。

 

6.测试数据:

          哈夫曼树的建立_第3张图片 

         哈夫曼树的建立_第4张图片

3.2系统设计

 

1.数据的定义:

结构体的定义:

    哈夫曼树的建立_第5张图片

  结构体类型指针及数组的定义:

 

2.基本操作及伪码算法:

  ①初始化结构体数组

  ②快速排序

     哈夫曼树的建立_第6张图片

 ③选择权值最小的两个合并

    哈夫曼树的建立_第7张图片 

④赫夫曼树的遍历

   哈夫曼树的建立_第8张图片

 

3.函数调用图

        哈夫曼树的建立_第9张图片        

4.主程序

 哈夫曼树的建立_第10张图片

 

3.3系统实现

 

1.基础算法:

     

① 将所有左,右子树都为空的作为根节点;

      ② 在森林中选出两根节点的权值最小的树作为一棵树的左,右子树,且置新树的附加根节点的权值为其左,右子树上根节点的权值之和,其中左子数的权值小于右子树的权值;

      ③ 从森林中删除这两颗树,同时把新树加入到森林中;

      ④ 重复②,③步骤,直到森林中只有一棵树为止,此树便是赫夫曼树。

 

2.问题分析及解决:

 

在掌握算法原理后,我着手实践。因为最后的赫夫曼树有2n-1个节点,于是我开一个大小为2n-1的结构体类型的数组存储权值,其中前n个空间用来存储排序好的原来的二叉树的权值,后n-1个存储空间用来存储每次选出的两个最小的权值之和,在测试了几组数据后发现有的结果出错,经过分析发现,判定过最小的权值后,在下一次选取最小值时进行了重复判断,对结果产生了干扰。于是我另外设定了一个数组判断是否在之前已经判断过,终于解决了问题。

后来发现纯数字的输出形式看不出子树与双亲之间的对应关系。翻阅数据结构书时,看到广义表,于是我想到用加括号的方法,即先判断一个节点是否有左子树(在赫夫曼树中有左子树就一定有右子树),如果有就输出括号,左右子树之间用逗号相隔。这样便增加了直观可读性。

 

3.回顾与分析:

          

本课程设计主要采用结构体类型指针、各函数相互调用的框架,实现了赫夫曼树的建立,其中对纯数字进行建立赫夫曼树,在实际应用中可能需要进行字符替换,在这一方面需要改进。通过程序的实现,进一步加深了对赫夫曼编码的理解。

 

4.算法的时空分析及改进

          

在进行排序操作时,若采用冒泡排序的方法,时间复杂度为O(n^2),空间复杂度为O(n),优点是简单易行,代码量少,缺点为运行速度慢。

          改进为快速排序,采用递归的方法,时间复杂度可降为O(nlogn),空间复杂度可降为O(logn)。优点是显著的提高了运算效率,缺点是快排不稳定,对于一些特殊的问题不适用。

 

3.4用户手册

 

1.运行程序;

2.输入节点数;

3.输入各个节点的权值;

4.观察运行结果;

5.结束。

 

3.5测试

 

1.运行程序;

2.输入节点数5;

3.输入权值4 8 9 2 3;

4.运行结果:

         哈夫曼树的建立_第11张图片  

5.结束。

 

4. 结束语

       

本次课程设计完成了赫夫曼树的建立,直观的显示出各子树与双亲的关系,有效地提高了执行效率.赫夫曼树的建立为其编码奠定基础,将来可以用于数据的压缩处理。

 

5. 参考资料

 

[1] 严蔚敏,吴伟民,《数据结构》(C语言版),清华大学出版社,2007

[2] 谭浩强,《C++程序设计》,清华大学出版社,2015

[3] Stanley B.LippmanBarbara E.Moo JoseeLaJolie,《C++ Primer》,人民邮电出版社, 2006

[4] KennethA.Reek,《C和指针》,人民邮电出版社,2008

[5] 博客,http://www.cnblogs.com/mcgrady/p/3329825.html

[6] 张颖江,胡燕,《C语言程序设计》,科学出版社,1998

6. 附录

#include 
#include 
#define N 20
using namespace std;
int p[100]={0}; //用来判断节点是否 被选取过 
typedef struct node         //建立哈夫曼树的结构体
{
	int data;
	struct node *lchild;   //定义各节点
	struct node *rchild;
	struct node *parent;
} BTNode;

void BTqsort(BTNode *ht,int low,int high)   //快排
{
	if(low>=high-1)
		return ;           //结束
	int key=ht[low].data;  //记录枢轴
	int i=low;
	int j=high-1;
	while(ikey) j--;  //前移
			if(idata;
			if(b->lchild!=NULL||b->rchild!=NULL)
				{
					cout<<"(";     //有左子树输出左括号
					DispBTNode(b->lchild);
					if(b->rchild!=NULL)    //有右子树 输出右括号
						cout<<",";
					DispBTNode(b->rchild);
					cout<<")";
				}
		}
}
	

int main()
{
	int n,i,temp;
	cout<<"************************"<>n;
		
			BTNode *m;
			BTNode w[2*N-1];
			if(n0)
				{
					cout<<"请依次输入二叉树各节点的权值:";
					for(i = 0; i < n; i++)
						{
							cin>>temp;
							w[i].data = temp;
						}
					m=CreateHT(w,n);
					cout<

 

 

 

你可能感兴趣的:(哈夫曼树的建立)