数据结构 ----- 堆

❤️ 堆实现

💟 1、什么是堆

释义:

堆是计算机科学中一类特殊的数据结构的统称,堆通常是一个可以被看做一颗完全二叉树的数组对象。

堆总是满足下列性质:

  • 堆中的某个结点的值总是不大于或不小于其父结点的值
  • 堆总是一颗完全二叉树

释义补充:

将根结点最大的堆叫做最大堆或者大根堆,根结点最小的堆叫做最小堆或小根堆

完全二叉树:一颗深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号i的结点在二叉树中的位置相同,则这颗二叉树称为完全二叉树。

如图(以二叉树为3层为例):

满二叉树:二叉树的层数为k,则其总结点数为2^k-1


完全二叉树:二叉树的层数为k,则其总结点数为 2^(k-1) ≤ N ≤2^k -1


最后一层结点数可能不满,但其结点必须从左到右依次排列,不能间隔。所以满二叉树为一种特殊的完全二叉树。

💝 2、堆源码查看

PS:本文主要分析堆实现过程中重点的思想,具体的堆实现代码请移步到代码仓库查看

堆实现源文件查看 ---------------------------------------------->堆实现源文件

堆实现头文件查看 ---------------------------------------------->堆实现头文件

💚 3、堆的基本操作

//初始化堆
void HeapInit(HP* heap);
//销毁堆
void HeapDestory(HP* heap);
//插入元素
void HeapPush(HP* heap, HeapDataType x);
//删除堆顶元素
void HeapPop(HP* heap);
//返回堆顶元素
HeapDataType HeapTop(HP* heap);
//判断堆是否为空
bool HeapEmpty(HP* heap);
//返回堆的size
size_t HeapSize(HP* heap);
//向下调整函数
void DownAdjusting(HeapDataType* a, size_t size);
//向上调整函数
void UpAdjusting(HeapDataType* a, size_t child);
//交换元素
void Swap(HeapDataType* child, HeapDataType* parent);

💜 4、向上调整算法、向下调整算法(重点)

🖊(一)向上调整

  • 代码查看
void UpAdjusting(HeapDataType* a, size_t child)
{
	size_t parent = (child - 1) / 2;
	//这里的循环判断条件不能为  parent>=0(在取<时,会多走一次循环条件) 或者 parent>0(最后一次不会进入,即parent为0时)
	while (child > 0)
	{
#ifdef SmallHeap
		if (a[child] < a[parent])
		{
			//交换父子节点
			Swap(&a[child], &a[parent]);
			//迭代
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
#endif  //SmallHeap
#ifdef BigHeap
		if (a[child] > a[parent])
		{
			//交换父子节点
			Swap(&a[child], &a[parent]);
			//迭代
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}

#endif // BigHeap
	}
}
  • 算法分析

1、向上调整算法用在对堆进行插入数据时。当将新的数据插进堆时,堆原本的结构被破坏了,所以需要向上调整算法进行重新建堆。

如图:

<img src="C:\Users\25584\AppData\Roaming\Typora\typora-user-images\image-20221101235824794.png" alt="image-20221101235824794" style="zoom:67%;" /

2、算法思想

  • 当我们插入数据后的二叉树时,会发现若抹去新插入的结点后,剩余结构为堆的形式。
  • 为了满足原来小根堆的结构,即父结点总是小于其子结点的结构,我们需要找到离新插入节点的最近的父节点,然后让其数据与父节点的数据进行比较,若其值比父节点小,则交换,否则就已满足小根堆结构。

交换过程如图:

<img src="C:\Users\25584\AppData\Roaming\Typora\typora-user-images\image-20221102001035220.png" alt="image-20221102001035220" style="zoom:67%;" /

不断使用向上调整算法后,此时的完全二叉树就又满足堆的性质。

✏️ (二)向下调整

  • 代码查看
void DownAdjusting(HeapDataType* a, size_t size)
{
	size_t parent = 0;
	size_t minchild = parent * 2 + 1;
	while (minchild < size)
	{
		//找出左右孩子最小的一个
		if (minchild + 1 < size && a[minchild + 1] < a[minchild])
		{
			minchild++;
		}
		//判断大小并交换
#ifdef SmallHeap

		if (a[minchild] < a[parent])
		{
			//交换
			Swap(&a[minchild], &a[parent]);
			//迭代
			parent = minchild;
			minchild = parent * 2 + 1;
		}
		else
		{
			break;
		}
#endif

#ifdef BIgHeap
		if (a[minchild] < a[parent])
		{
			//交换
			Swap(&a[minchild], &a[parent]);
			//迭代
			parent = minchild;
			minchild = parent * 2 + 1;
		}
		else
		{
			break;
		}
#endif // BIgHeap

	}
}
  • 算法分析

1、向下调整算法在堆实现过程中用在删除堆顶元素时。

当我们需要删除堆顶元素时,我们是将堆顶元素与最后一个元素进行交换,然后再令size自减后即可删除对堆顶元素

如图:

2、算法思想

  • 我们需要对删除堆顶数据后的二叉树进行调整,使他重新具有小堆的结构。
  • 此时的二叉树,除去堆顶数据后,剩余的结构仍保持堆的结构,所以只需要对堆顶元素使用向下调整算法即可
  • 因为小堆必须保证父结点小于其左右两个结点,所以我们需要对两个子结点进行比较大小,取最小的结点与父节点进行替换。

交换过程如图:

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kunmu.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值