数据结构之堆和堆排序(C语言版)

前言

各位读者朋友们大家好!这篇博客我们来讲一下数据结构的堆和堆排序以及代码的实现。

一. 堆的概念

堆是一种满足特定条件的完全二叉树,主要可分为两种类型:大顶堆和小顶堆。

  • 大顶堆: 父亲节点的值 >= 子节点的值。
  • 小顶堆: 父亲节点的值 <= 子节点的值。

在这里插入图片描述
堆还有以下性质:

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

二. 堆的实现

这里我们建大堆,如果要建小堆只需要调整修改大小逻辑判断(例如将<改为>)。

2.1 堆的存储与表示

因为堆总是一棵完全二叉树,所以我们用数组来存储堆会更加方便。当我们使用数组来实现堆的时候,很容易通过下标来找到某个节点的父亲节点和子节点。
在这里插入图片描述

  • 父亲节点:(i - 1) / 2
  • 子节点:2i + 1(左孩子节点)2i + 2(右孩子节点)

2.2 元素入堆

给定元素 val ,我们首先将其添加到堆底。添加之后,由于 val 可能大于堆中其他元素,堆的成立条件可能已被破坏,因此需要修复从插入节点到根节点的路径上的各个节点。
在这里插入图片描述
在对堆进行修复的时候,我们需要用到向上调整算法,即将比父亲节点大的节点的元素换到父亲节点的位置,父亲节点的元素跟该子节点交换。向上调整算法要求调整数据位置之前的数据是一个堆。

向上调整算法
void AdjustUp(HPDataType* a, int child)
{
   
   
	int parent = (child - 1) / 2;
	while (child > 0)
	{
   
   
		if (a[parent] < a[child])
		{
   
   
			Swap(&a[parent], &a[child]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
   
   
			break;
		}
	}
}

在这里插入图片描述

2.3 删除堆顶元素

堆顶元素是二叉树的根节点,即数组首元素。如果我们直接从数组中删除首元素,那么堆的所有节点的索引都会发生变化,这将使得后续进行修复变得困难。为了尽量减少元素索引的变动,我们将堆顶元素与最后一个元素进行交换,然后删除最后一个元素,再进行堆的调整。
在这里插入图片描述
这里需要使用向下调整算法,我们在删除堆顶数据的时候,并没有破坏左子树和右子树的堆的属性,因此我们在向下调整时,只需比较根节点的值与左右子节点的值,如果小于子节点的值只需与子节点中较大的一个进行交换,直到调整到叶子节点即可。

向下调整算法
//parent是父亲节点的下标,n是数组的元素个数
void AdjustDown(HPDataType* a, int parent, int n)
{
   
   
	int child = 2 * parent + 1;
	while (child < n)//child>=n就说明到叶子节点了
	{
   
   
		//找左右孩子中较大的一个
		if (child + 1 < n && a[child] < a[child + 1])//防止越界
		{
   
   
			
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值