数据结构-----哈夫曼树的构造以及遍历

简介: /*根据Huffman树的构造原理进行构造 ... 哈夫曼树在编码压缩的领域有很好的应用,利用Huffman进行编码可以保证数据传输的无二义性 。但是要注意的是 对于出现频率大的数据我们应该尽量放在离根节点近的地方进行编码 ,出现频率小的数据我们可以放在距离根节点小的地方。
/*
根据Huffman树的构造原理进行构造  ... 
哈夫曼树在编码压缩的领域有很好的应用,利用Huffman进行编码可以保证数据传输
的无二义性 。
但是要注意的是 对于出现频率大的数据我们应该尽量放在离根节点近的地方进行编码 ,
出现频率小的数据我们可以放在距离根节点小的地方。
这样可以提高数据的传输效率 。
*/
#include "stdio.h"
#include "malloc.h" 

///节点声明
typedef struct  node{
    node *lChild ;
	node *rChild ;
	int data ;//权值
}TreeNode ; 
TreeNode * CreateHuffmanTree(int a[],int n)  ; //数组a表示权的数组  n是个数 
void  FindLittle(int *x1,int *x2 ,TreeNode**pArr,int n)  ; //查找出2个权值最小的节点的下标 


TreeNode * CreateHuffmanTree(int a[],int n)   //数组a表示权的数组  n是个数 
{     
	TreeNode**pArr=(TreeNode**)malloc(sizeof(TreeNode*)*n);  //动态产生指针数组
	TreeNode*p =NULL;//用于返回哈夫曼树的根节点的指针 
	int k1,k2 ;  //k1代表最小权  k2代表次小权    用于做为 FindLittle的参数查找最小权下标
	for(int i=0;i<n;i++)
	{
		pArr[i]=new TreeNode ;    //为节点指针数组动态分配指向的对象
		pArr[i]->data=a[i]  ;
		pArr[i]->lChild=pArr[i]->rChild=NULL ;//初始化每个节点的左右节点都是空    
	}
	
	///因为哈夫曼树是循环的从节点数组中找出权值最小的两个节点进行组合 并从数组中删除这两个节点,并把合并后的节点添加到数组中。
	for(i=0;i<n-1;i++) //因为最后还剩下一个节点所以就会挑选n-1次 
	{
		FindLittle(&k1,&k2,pArr,n) ; //查找2个最小权节点下标 
		p=new TreeNode;   //循环组合最后的p指向的节点便是最终的pRoot 
		p->data=pArr[k1]->data+pArr[k2]->data  ;
		p->lChild=pArr[k1] ;
		p->rChild=pArr[k2] ;  
		
		pArr[k1]=p    ;   //将合并后的新节点赋值给pArr最小的那个下标
		pArr[k2]=NULL ;   // 次下标设置NULL, k1和k2也可以反过来这个具体我们自己定
		
	}
	free(pArr) ;//释放指针数组  
	return p;  
}


void  FindLittle(int *x1,int *x2 ,TreeNode**pArr,int n)  //查找出2个权值最小的节点的下标
{
	int  k1,k2;  //保存权最小的两个节点下标 
	k1=-1 ; //表示没有找到数据
	for(int i=0;i<n;i++)    //找出其中的前两个元素不为NULL的下标
	{  
		if(pArr[i]!=NULL&&k1==-1)
		{
			k1=i ;     //第一个下标
			continue ;
		}
		if(pArr[i]!=NULL) 
		{
			k2=i ;
			break;//找到第二个下标退出循环
		}
	}
	
	////// 最小权的2个下标的搜索实现//////////    
	for(i=k2;i<n;i++) //我们是先获取k1  后获取k2所以一开始 一定是从k2开始循环的 
	{ 
	if(pArr[i]!=NULL)
	{
        if(pArr[i]->data<pArr[k1]->data )  //如果下标k1的权 小于当前下标的元素的权 
		{  
			k2=k1;  //此时还是k1<k2满足我们返回的结果
			k1=i ;
		}
		else if(pArr[i]->data<pArr[k2]->data)
		{
			k2=i ;
		}
		
	}	 
	}
	*x1=k1  ;
	*x2=k2  ;
}

///哈夫曼树的先序遍历 
void PreHufOrder(TreeNode*p)   //先序遍历
{  
	if(p!=NULL)
	{
		printf("%d ",p->data) ; 
		PreHufOrder(p->lChild) ;
		PreHufOrder(p->rChild) ;
	} 
}

//中序遍历  
void InHufOrder(TreeNode*p)
{
	   if(p!=NULL)
	   {
		   InHufOrder(p->lChild) ;
		   printf("%d ",p->data) ;
		   InHufOrder(p->rChild) ;
	   }
}
//后续遍历 
void PostHufOrder(TreeNode*p)
{
	if(p!=NULL)
	{
		InHufOrder(p->lChild) ;
		InHufOrder(p->rChild) ;
		printf("%d ",p->data) ;
	}
}
//清空树  
void ClearHufTree(TreeNode*p)
{
	if(p!=NULL)
	{
		ClearHufTree(p->lChild) ;
		ClearHufTree(p->rChild) ;
		delete p ;
	}
}

int main()
{
    int a[]={3,5,3,8,7,9,4,2,4,5,6,3,2,3} ;  //权值 
    TreeNode*p=::CreateHuffmanTree(a,sizeof(a)/sizeof(int)) ; //创建huffman树
	printf("Huffman前序遍历:\n") ;
    PreHufOrder(p) ;  //前序遍历huffmanTree
	printf("\n");
	printf("Huffman后序遍历:\n") ;
	PostHufOrder(p) ;//后序遍历
	printf("\n");
	printf("Huffman中序遍历:\n") ;
	InHufOrder(p) ;//中序遍历
	printf("\n");
	ClearHufTree(p) ;//清空树
	return  0 ;
}

目录
相关文章
|
8月前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
185 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
8月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
245 3
|
8月前
|
数据采集 存储 算法
【C++数据结构——图】图的遍历(头歌教学实验平台习题) 【合集】
本文介绍了图的遍历算法,包括深度优先遍历(DFS)和广度优先遍历(BFS)。深度优先遍历通过递归方式从起始节点深入探索图,适用于寻找路径、拓扑排序等场景;广度优先遍历则按层次逐层访问节点,适合无权图最短路径和网络爬虫等应用。文中提供了C++代码示例,演示了如何实现这两种遍历方法,并附有测试用例及结果,帮助读者理解和实践图的遍历算法。
303 0
|
11月前
|
存储 编译器 C++
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
119 4
|
12月前
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
231 6
|
12月前
|
存储 C语言
数据结构基础详解(C语言): 树与二叉树的应用_哈夫曼树与哈夫曼曼编码_并查集_二叉排序树_平衡二叉树
本文详细介绍了树与二叉树的应用,涵盖哈夫曼树与哈夫曼编码、并查集以及二叉排序树等内容。首先讲解了哈夫曼树的构造方法及其在数据压缩中的应用;接着介绍了并查集的基本概念、存储结构及优化方法;随后探讨了二叉排序树的定义、查找、插入和删除操作;最后阐述了平衡二叉树的概念及其在保证树平衡状态下的插入和删除操作。通过本文,读者可以全面了解树与二叉树在实际问题中的应用技巧和优化策略。
278 2
|
11月前
|
存储 算法
数据结构与算法学习十六:树的知识、二叉树、二叉树的遍历(前序、中序、后序、层次)、二叉树的查找(前序、中序、后序、层次)、二叉树的删除
这篇文章主要介绍了树和二叉树的基础知识,包括树的存储方式、二叉树的定义、遍历方法(前序、中序、后序、层次遍历),以及二叉树的查找和删除操作。
148 0
【数据结构】遍历二叉树(递归思想)-->赋源码
【数据结构】遍历二叉树(递归思想)-->赋源码
106 4
|
存储 算法 Python
“解锁Python高级数据结构新姿势:图的表示与遍历,让你的算法思维跃升新高度
【7月更文挑战第13天】Python中的图数据结构用于表示复杂关系,通过节点和边连接。常见的表示方法是邻接矩阵(适合稠密图)和邻接表(适合稀疏图)。图遍历包括DFS(深度优先搜索)和BFS(广度优先搜索):DFS深入探索分支,BFS逐层访问邻居。掌握这些技巧对优化算法和解决实际问题至关重要。**
143 1
|
机器学习/深度学习 存储
数据结构学习记录——哈夫曼树(什么是哈夫曼树、哈夫曼树的定义、哈夫曼树的构造、哈夫曼树的特点、哈夫曼编码)
数据结构学习记录——哈夫曼树(什么是哈夫曼树、哈夫曼树的定义、哈夫曼树的构造、哈夫曼树的特点、哈夫曼编码)
426 1