数据结构——第五讲、树(堆、哈夫曼树和集合)

数据结构第五章(三) -树与二叉树的应用 我们讲了树的存储方式,还有树、森林怎么遍历,还有哈夫曼编码、并查集,要注意的就是并查集的两重优化策略是怎么优化的。还有一个容易混的就是树的后根是二叉树的中序,森林的中序也是二叉树的中序,所以树的后根就是森林的中序。 阅读详情

5.1 堆

  当需要存储一个不同优先级的优先队列时(总是删除最大/最小值,插入任意元素),我们就要用到堆,当然,用数组,链表,或树都可以完成,但是算法复杂度不够理想。
  堆是一种特殊的树,它的任意节点都比它的左右儿子大/小,所以它的根节点是最大的/最小的,删除的时候只需要删除最上面的根节点即可,插入时,为了使空间利用率最大,按照完全二叉树插入,这就是最大/小堆
  还记得刚开始说二叉树的时候,我们试过用数组存储二叉树,然而因为利用率不高,只适合存完全二叉树这种排的比较满的树,对于现在堆这种结构,我们就可以用数组来存,从上到下一层一层排序,第i个节点左儿子是2i,右儿子是2i+1,父节点是i/2。

操作集:

MaxHeap Create(int MaxSize);
Boolean IsFull(MaxHeap H);
Boolean IsEmpty(MaxHeap H);
MaxHeap Insert(ElementType x, MaxHeap H);
ElementType Delete(MaxHeap H);
  • 最大堆的结构
typedef struct HeapStruct *MaxStruct;
struct HeapStruct{
	//指向数组
	ElementType *Elements;
	//现有元素个数
	int Size;
	//最大容量
	int Capacity;
};
  • 创建一个最大堆
MaxHeap Create(int MaxSize){
	MaxHeap H = malloc(sizeof(struct HeapStruct));
	//数组空出一个位置存放最大值作为哨兵
	H->Elements = malloc(sizeof((MaxSize+1)*ElementType));
	H->Size = 0;
	H->Capacity = MaxSize;
	//宏定义一个数据里面的最大可能值,插入时可以减少一个判断条件。
	H->Elements[0] = MaxData;
	return H;
}
  • 插入
MaxHeap Insert(ElementType x, MaxHeap H){
	int i;
	if(IsFull(H)){
		printf("已满!");
		return NULL;
	}
	//改变最大堆信息的同时,告诉i应该插入的位置
	i = ++H->Size;
	for(;H->Elements[i/2] < x;i /= 2){
		H->Elements[i] = H->Elements[i/2];
	}
	H->Elements[i] = x;
	return H;
}
  • 删除
ElementType Delete(MaxHeap H){
	if( IsEmpty(H) ){
		printf("堆空!");
		return NULL;
	}
	ElementType MaxItem = H->Elements[1];
	ElementType item;
	int parent = 1;
	int child;
	item = H->Elements[H->Size--];
	for(;2*parent <= H->Size;parent = child){
		child = 2 * parent;
		if( child != H->Size){
			if( H->Elements[child] < H->Elements[child+1])
				child++;
		}
		if(item >= H->Elements[child])break;
		else
			H->Elements[parent] = H->Elements[child];
	}
	H->Elements[parent] = item;
	return MaxItem;
}

  给定一个序列,创建一个堆,可以通过不断插入的方式创建。但是有效率更高的方法,先把序列存入完全二叉树中,然后从最后一个有儿子的节点开始调整,形成一个节点,他的左右儿子都是堆的递归

//这段代码未经验证,有什么问题希望能反馈给我……
MaxHeap Create(ElementType T[Size]){
	MaxHeap H;
	for(int i = 0; i < Size; i++)
		H->Elements[++H->Size] = T[i];
	int parent = H->Size/2;
	int child;
	ElementType t;
	for(;parent>0;parent--){
		for(;2*parent <= H->Size;parent = child){
			child = 2 * parent;
			if( child != H->Size){
				if( H->Elements[child] < H->Elements[child+1])
					child++;
			}
			if(H->Elements[parent] >= H->Elements[child])break;
			else{
				t = H->Elements[parent];
				H->Elements[parent] = H->Elements[child];
				H->Elements[child] = t;
			}
		}
	}
}

5.2 哈夫曼树和哈夫曼编码

  查找或者使用数据时,不是平均的使用每一个数据,而是有的数据频率高,有的数据频率低,不同的频率可以视为数据不同的权重,这些带权重的数据在树中的分布会影响到查找的效率。
  树中的每个叶节点都有自己的权重,从根节点到叶节点经过的路径乘以叶节点的权重作为某个叶节点的带权路径长度,所有的叶节点的带权路径长度之和就是该树的带权路径,哈夫曼树就是带权路径最小的树。

  构造哈夫曼树: 在数据中找到权值最小的的两个,组成一个树,这棵树的权值就是他们两个权值的和,然后这棵新树的根节点作为新的节点放入原来的数据中。

typedef struct TreeNode *HuffmanTree;
struct TreeNode{
	int weight;
	HuffmanTree Right,Left;
};
//事先将元素按权值构成最小堆。传入最小堆,返回哈夫曼树。
HuffmanTree Huffman(MinHeap H){
	HuffmanTree T;
	for(int i = 1; i < H->Size; i++){
		T = malloc(sizeof(struct TreeNode));
		T->Left = Delete(H);
		T->Right = Delete(H);
		T->weight = T->Left->weight+T->Right->weight;
		Insert(T,H);
	}
	T = Delete(H);
	return T;
}

哈夫曼树有几个特点:

  • 没有只有一个儿子的节点(也就是度为1的节点)
  • 如果有n个叶节点,总结点数为2n-1
  • 如果有权值一样的元素,有可能会构成不同结构的树,但是他们的总路径是相同的
  • 哈夫曼树左右儿子交换位置之后任然为哈夫曼树。

  哈夫曼编码:对于使用频率高的字符,我们需要用更简洁的表示方法,但是用不等长的编码方法就会出现二义性问题,同样的二进制码可以表示不同的意义,为了避免这种情况,我们就要用到哈夫曼树,每个节点的分支都有0和1来表示,要编码的字符都在树的叶节点上,这样就可以避免二义性问题,再把不同频率作为权值,就可以用哈夫曼树做哈夫曼编码。(这让我想到了有的CPU指令集)。

5.3 集合及其运算

  把一个个的元素看成一个个的集合,如果两个元素之间联通,那么就把这两个集合并起来。
  集合我们只关心两个问题,并集和查找,查找就是找到元素所在的那个集合,为此,我们用树来存储集合,用树的根表示该集合,求并集的时候只需要把一棵树接在另一个树上即可。
  用树的结构表示集合,在计算机中,我们可以用结构数组来存储这种树,Parent表示该节点的父节点在数组中的位置,根节点的Parent为-1,注意,一个数组可以存好几个不同的集合,也可以只有一个集合。
  其实就是数据库中的那种递归字段

typedef struct {
	ElementType Data;
	int Parent;
}SetType;
  • 查找,输入结构数组和要查找的元素,返回元素所在的集合(即该集合树的根节点)。
int Find(ElementType x, SetType S[]){
	int i;
	for(i = 0; i < MaxSize && S[i].Data != x; i++);
	if(i >= MaxSize)return -1;
	//此处的条件为大于等于0,其实也可以用“不等于-1”,但是因为后面的并操作会用
	//根节点的Parent值存储别的信息,所以不用“不等于-1”
	for(;S[i].Parent >= 0;i = S[i].Parent);
	return i;
}
  • 并,parent值用集合元素个数的负值表示(负值小的个数多)
void Union(SetType S[], ElementType x1, ElementType x2){
	int root1,root2;
	root1 = Find(x1,S);
	root2 = Find(x2,S);
	if(root1 != root2){
		if(S[root1].Parent < S[root2].Parent){
			S[root1].parent += S[root2].parent;
			S[root2].parent = root1;
		}
		else{
			S[root2].parent += S[root1].parent;
			S[root1].parent = root2;
		}
	}
}
408《数据结构》——第五章:树与二叉树 树是n (n ≥ 0)个结点的有限集合。当n = 0时,称为空树。当n > 0时,满足:有且仅有一个特定的称为根 (Root)的结点。其余结点可分为m (m ≥ 0)个互不相交的有限集合,其中每个集合本身又是一棵树,称为根的子树 (Subtree)。树是一种递归定义的数据结构。基本术语:结点拥有的子树个数。树内各结点度的最大值。度为0的结点。度大于 0的结点。一个结点的子树的根称为该结点的孩子。一个结点是其所有子树根的双亲。具有相同双亲的结点。从根到该结点所经分支上的。 阅读详情

相关推荐

数据结构——第五章树(详细知识点总结)

【知识框架】 5.1 树的基本概念 5.1.1 树的定义 树是n(n>=0)个节点的有限集。当n=0时,称为空树。 在任意一棵非空树中应满足: 有且仅有一个特定的称为根(Root)的结点。 当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2,…Tm,其中每个集合本身又是一棵树,并称为根的子树(SubTree)。 显然,树的定义是递归的,即在树的定义中又用到了其自身,树是一种递归的数据结构。 树作为一种逻辑结构,同时也是一种分层结构,有以下两个特点: 树的根结点没有前

疯子书生的博客 2305

【数据结构09】哈夫曼树(最优二叉树)详解,及Java实现

哈夫曼树(最优二叉树 概述 哈夫曼树又称为最优树. 1、路径和路径长度 在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。 通路中分支的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。 2、结点的权及带权路径长度 若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。 结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。 3、树的带权路径长度 树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL。 给定N个

博客 873

信创改造实战:SpringBoot项目迁移到宝兰德BES 9.5.5的完整避坑指南(附依赖配置)

本文详细介绍了将SpringBoot项目迁移到宝兰德BES 9.5.5中间件的完整流程,包括环境准备、依赖调整、Web.xml版本适配、部署配置优化及常见问题解决方案。特别针对信创改造需求,提供了排除Tomcat依赖、处理BES专用starter等实用技巧,帮助开发者顺利完成国产中间件迁移。

weixin_30825581的博客 1095

4.6(补) 哈夫曼树与集合运算

伪码 ...

Kasuganowxx的博客 214

NRF52832调试方法1——HardFault_Handler问题定位

一、遇到问题 keil debug模式下,直接点击全速运行(Run)发现程序卡死,点击stop按钮后,停到了HardFault_Handler位置,如下图所示。 此时使用navigate backwards(蓝色左箭头)是无效的,找不到程序卡在哪里。 二、解决办法 此时首先观察register窗口 若Stack为MSP,则复制R13(SP)的值到memory观察窗的地址搜索栏。每一行显示连续的28个地址上的存储信息,每个地址上存有一个字节。 从第21个位置起的连续四个字节是LR的值,

小梁的博客 3650

从零开始:用ADS 2023手把手教你设计2.4GHz Wi-Fi LNA(基于ATF-54143,附模型文件)

本文详细介绍了如何使用ADS 2023软件设计2.4GHz Wi-Fi频段的低噪声放大器(LNA),基于ATF-54143晶体管。内容涵盖模型导入、直流工作点确定、稳定性优化、噪声匹配等关键步骤,并提供可下载的模型文件包,帮助工程师快速掌握LNA设计技巧。

weixin_42531128的博客 319

【数据结构】2.树:堆、哈夫曼树、集合

# 一、堆 ## 1.基本概念 优先队列(Priority Queue):特殊的“队列”,取出元素的顺序是依照元素的优先权(关键字)大小,而不是元素进入队列的先后顺序。 堆是优先队列的完全二叉树组织形式。 堆的两个特性: **结构性:用数组表示的完全二叉树; 有序性:任一结点的关键字是其子树所有结点的最大值(或最小值)。**

深思深练 厚积薄发 555

Excel也能玩转K-means聚类?手把手教你用表格搞定用户分群(附完整公式)

本文详细介绍了如何在Excel中实现K-means聚类算法,无需编程即可完成用户分群。通过SUMIF、SQRT等基础函数,从数据预处理到最终分群全流程手把手教学,特别强调数据标准化和迭代优化的关键步骤,帮助运营团队低成本高效分析用户行为数据。

weixin_30555125的博客 180

408数据结构第五章 树与二叉树

本章内容较多,讲解了树、森林、并查集等多种数据结构及其操作原理与代码实现

m0_74983085的博客 2473

《电磁兼容设计》专栏说明

本专栏自2024年1月起开始更新,仅设此一个电磁兼容相关知识专栏,并将一直持续更新下去,无期限

linkking27的博客 790

RK35X8调试YT8531单网口千兆以太网PHY芯片,修复ping不通或者IP地址丢失的问题

RK35X8上调试YT8531以太网PHY

荻夜的博客 3971

《数据结构》-第五章 树和二叉树(知识点总结)

第五章 树与二叉树 从本章开始学习非线性数据结构,树作为一类重要的一对多的数据结构的代表,以分支结构关系定义层次结构,在现实生活中很多关系都可以用树形结构表示,其中二叉树更是最常出现的一种表现方式。 因此,在考试过程中,会涉及选择题(几率大)、填空题、综合应用题和算法题各方面,同时所占分值较大,要对本章内容重点把握。 【考点】①树的基本概念 ②二叉树: 掌握二叉树的定义及其主要特征; 二...

大家一起进步叭 6247

26、遥感图像无监督变化检测方法解析

本文详细解析了遥感图像中的无监督变化检测方法,重点介绍了基于快速模糊 C-均值聚类的无监督变化检测方法(CDFFCM)在滑坡映射中的应用。CDFFCM 方法利用图像结构信息和高斯金字塔技术,提高了检测的准确性,减少了参数数量,并缩短了计算时间。该方法通过与传统方法的对比,展现出在高分辨率遥感图像滑坡检测中的显著优势。此外,文章还探讨了 CDFFCM 的未来发展趋势,包括技术融合、多模态数据应用以及智能化与自动化方向。

game4的博客 148

866数据结构笔记 - 第五章 树和二叉树

866数据结构、湖南大学考研、树和二叉树

qq_45331246的博客 3997

虚幻商城 蓝图汇总

虚幻引擎是一个非常强大和灵活的游戏开发工具,拥有众多的蓝图可以帮助我们更高效地工作。

一碗清深的博客 1506

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

数据结构 第五章 树和二叉树——树和森林及哈夫曼树

树、森林和哈夫曼树

weixin_62917800的博客 646

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

数据结构(C语言版)第五章树和二叉树

数据结构(C语言版)第五章树和二叉树

2301_76828807的博客 1664

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

王道数据结构课代表 - 考研数据结构 第五章 树和二叉树 究极精华总结笔记

数据结构与算法 笔记导航🚥🚥🚥 🥬 第一章 绪论 🥕 第二章 线性表 🥪 第三章 栈和队列 🍊 第四章 串-KMP(看毛片算法) 🍒 第五章 树和二叉树 🍀 第六章 图 🍚 第七章 查找(B树、散列表) 🧄 第八章 排序 (内部排序:八大排序动图演示与实现 + 外部排序) 🍔 数据结构与算法 复试精简笔记 🎨 408 全套初复试笔记汇总 传送门 🏃‍🏃‍🏃‍ 如果本篇文章对大家起到帮助的话,跪求各位帅哥美女们,求赞👍 、求收藏、求关注!

clzZ2的博客 7557

第五章 树与二叉树

本章内容多以选择题或综合题的形式考查,但统考也会出涉及树遍历相关的算法题。树和二叉树的性质、遍历操作、转换、存储结构和操作特性等,满二叉树、完全二叉树、线索二叉树、哈夫曼树的定义和性质,都是选择题必然会涉及的内容。

tridoron6的博客 1754

#数据结构#第五章:树、森林、哈夫曼树

文章目录判断题单选题程序填空题编程题7-1 树的同构7-2 家谱处理7-3 修理牧场 判断题 1-1.对于一个有N个结点、K条边的森林,不能确定它共有几棵树。 F 1-2.对N(≥2)个权值均不相同的字符构造哈夫曼树,则树中任一非叶结点的权值一定不小于下一层任一结点的权值. T 单选题 2-1.具有1102个结点的完全二叉树一定有__个叶子结点。 A.79 B.551 C.1063 D.不...

vircorns的博客 5693

构建哈夫曼树方法

每个权值(权重)视为一棵只有一个节点的单独树,并将这些树组成一个“森林”。每个节点权值对应一个叶子节点。它利用权值较小的节点优先组合的原则,逐步构造一棵总带权路径长度最小的二叉树。堆排序能快速找到权值最小的两棵树,其时间复杂度为。为了快速找到森林中权值最小的两个树,通常使用。(优先队列)来存储这些树。

Weiki的博客 1250

数据结构期末复习三------哈夫曼树与WPL

哈夫曼树又名最优二叉树,指的是当叶子结点带有权值时,通过已知的叶子结点以及相应的权值可以构造出来的带权路径长度最小的二叉树。这就要求权值越大的叶子结点越靠近根结点,而权值越小的叶子结点越远离根结点。

2401_83961434的博客 1180

【数据结构初学笔记14】第五章堆、哈夫曼树、集合

浙江大学陈越数据结构MOOC慕课初学笔记14第五章堆、哈夫曼树、集合

m0_50662459的博客 186

【数据结构】(Python)第五章:树

数据结构(Python)第五章:树

qq_45704789的博客 722

数据结构(陈越,何钦铭) 第五讲 树(下)

int Size;return H;int i;printf("最大堆已满");for(;int i;for(i=1;i<H->Size;}//整体复杂度为O(NlogN)

qq_44845100的博客 223

26考研 | 王道 | 数据结构 | 第五章 树

有且仅有一个特定的称为根的节点当n>1时,其余结点可分为m (m >0) 个互不相交的有限集合,其中每个集合本身又是一棵树,并且称为根结点的子树互不相交就是仅有一个前驱树是一种递归的数据结构有且仅有一个根节点没有后继的结点称为“叶子结点”(或终端节点)有后继的结点称为“分支结点” (或非终端结点)除了根节点外,任何一个结点都有且仅有一个前驱每个结点可以有0个或多个后继基本术语祖先结点:从自己出发走到根结点的最短路这条路径上的所有节点都是祖先节点。

m0_74795952的博客 2049
上一篇: 数据结构——第四讲、树(二叉搜索树与平衡二叉树)
下一篇: 数据结构——第六讲、图(图、图的遍历、最短路径、最小生成树和拓扑排序)
Suzuki Mirai
博客等级 码龄9年 17粉丝 55原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值