堆的基本知识

博客介绍了堆的相关知识,堆是满足特定性质的完全二叉树,有大顶堆和小顶堆之分。可用数组存储二叉树,给出了结点索引计算公式。还讲解了二叉树的shiftUp和shiftdown操作,前者用于插入元素后排序成最大堆,后者用于取出元素后排序成最大堆。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、堆的定义
首先,堆是完全二叉树(二叉树:每个结点有两个子节点),它满足如下性质:
(1)任何一个结点都不大于其父结点,这种堆称为大顶堆 或者 任何一个结点都不小于其父结点,这种堆称为小顶堆
(2)需要是完全二叉树,最后一层在最左侧

2、用数组来存储二叉树
首先给二叉树从左至右,从上至下来给每个结点编号,如此编号后,子结点的左结点是父结点的二倍,子结点的右结点是父结点的2倍加1。
在这里插入图片描述
之后,就可以用如下图的数组来存储这个堆了,该数组从1开始计数,以符合这个堆的索引。
在这里插入图片描述
这里要解释一下的是:
第i个结点的父结点的索引计算公式是:parent(i)=i/2 这里的"/"是计算机里的除号,取整符。
第i个结点的子结点分别是:left child(i)=2i;right child(i)=2i+1。
根据这个公式,就可以在数组中索引相应的结点数据了
3、二叉树shiftUp操作
作用:将插入的元素放到堆的最后一个叶子,并且对堆进行排序,使其成为最大堆。如下图所示:
在这里插入图片描述
方法:由于没插入此元素之前,这个堆是最大堆,新插入的元素要做的就是将它和父结点比较,如果大于父结点,就和父结点调换位置,接下来继续比较调换过父结点和其上一层父结点。直至形成最大堆
代码如下:

void __shiftup(int k)
	{
		while (k>1 && data[k / 2]<data[k])
		{
			std::swap(data[k / 2], data[k]);
			k = k / 2;
		}
	}
void insert(T item)
	{
	//如果堆里的数据超过容纳总量,则报错
		assert(capcity > count + 1);
		//将元素插入数组
		data[count + 1] = item;
		count++;
		//将元素插入完全二叉树,传入参数是数组的最后一个索引
		__shiftup(count);
	}

在第k个节点插入元素,并对其进行shiftup操作。
4、shiftdown操作
作用:从堆中取出一个元素后,将堆排序成最大堆。
从堆中取出元素的方法:先将第一个元素取出,然后将最后一个元素放到第一个元素位置。同时count–。然后将第一个元素与两个子节点比较,如果子节点比该元素大,则交换父结点和子节点的元素。之后继续比较交换过的这个子节点和该子节点下面的子节点。
如下图:先取出data[1],然后将data[11]和data[1]交换

交换后形成下图的这个二叉树。
在这里插入图片描述
由于该二叉树的data[1]<子节点的最大值data[2],所以需要将data[1]与data[2]交换
在这里插入图片描述
接下来继续比较data[2]他的两个子节点data[4],data[5]。这里,需要交换data[2]和data[5]。形成下图所示的树。
在这里插入图片描述
代码如下:

	void __shiftdown(int k)
	{
	//如果左子节点存在,则需要一直执行shiftdown操作
		while (2 * k <= count)
		{
		//如果存在右子节点,比较左右子节点,将大的节点的索引放到j里面
			int j = 2 * k;
			if (2 * k + 1 <= count&&data[j]<data[2 * k + 1])
			{
				j = 2 * k + 1;
			}
			//如果父结点小于左子节点,则调换位置
			if (data[k]<data[j])
			{
				swap(data[k], data[j]);
			}
			else
			{
				break;
			}
		}
	}
	T extraMax()
	{
		T result = data[1];
		data[1] = data[count];
		count--;
		__shiftdown(1);
		return result;
	}
CTF入门基础知识是指在CTF(Capture The Flag)比赛中,掌握关于(heap)的一些基础知识是计算机内存的一部分,用于存储动态分配的数据。在中,数据可以通过malloc()和free()这样的函数进行分配和释放。 为了应对CTF相关的问题和挑战,以下是几个基础知识点: 1. 管理:了解内存的布局,包括段(heap segment)的起始地址、结束地址以及分配的内存块。此外,还需要了解块(heap chunk)的结构,包括块的头部和尾部。块中的元数据通常用于管理分配和释放。对于不同的管理器,其块结构可能有所不同。 2. 溢出漏洞:溢出是一种常见的漏洞类型。当程序没有正确地管理内存时,会导致溢出漏洞。攻击者可以通过溢出篡改重要的数据或劫持程序流程。学习如何利用溢出漏洞可以帮助我们理解程序的弱点以及如何加强安全性。 3. 分配技巧:在CTF中,有时需要进行分配,比如分配特定大小的块或者创建一定数量的块。掌握一些分配技巧可以帮助我们解决一些相关的CTF问题。 4. 利用技术:了解利用技术是掌握CTF基础的重要部分。常见的利用技术包括重叠块、fastbin攻击、unsorted bin攻击等。通过这些技术,攻击者可以在利用溢出漏洞时实现特定的攻击目标。 以上是CTF入门基础知识的一些关键点。通过学习和实践,逐渐掌握这些知识可以帮助我们在CTF比赛中更好地理解和解决相关的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值