一文学会数据结构-堆

 更新时间:2021年08月26日 16:45:08   作者:双鱼211  
本文主要介绍了数据结构-堆,文中通过图片和大量的代码讲解的非常详细,需要学习的朋友可以参考下这篇文章,希望可以帮助到你

1.堆

大根堆:所有父节点大于等于孩子节点

在这里插入图片描述

小根堆:所有父节点小于等于孩子节点

在这里插入图片描述

堆的性质:

• 堆中某个节点的值总是不大于或不小于其父节点的值

• 堆总是一棵完全二叉树

2.堆的实现

堆的实现请点击—> 实现堆排序实例

现在我们给出一个数组,逻辑上看做一颗完全二叉树。我们通过从根节点开始的向下调整算法可以把它调整成一个小堆。

int a[] = {27,15,19,18,28,34,65,49,25,37};

2.1堆的向下调整算法(建小堆)

向下调整算法-前提:当前树的左右子树必须都是一个小堆
向下调整算法的核心思想:选出左右孩子中小的哪一个,跟父亲交换,小的往上浮,大的往下沉,如果要建大堆则相反

如下图所示为一个向下调整法调小堆

在这里插入图片描述

2.2 堆向下调整算法(建小堆)实现

//堆向下调整算法
//建小堆
void AdjustDown(int* a, int n, int root)
{
	int parent = root;
	int child = parent * 2 + 1;
	//孩子超过数组下标结束
	while (child < n)
	{
		//child始终左右孩子中小的那个
		if (a[child + 1] < a[child] && child + 1 <n)//防止没有右孩子
		{
			++child;
		}
		//小的往上浮,大的往下浮
		if (a[child] < a[parent])
		{
			int tem = a[parent];
			a[parent] = a[child];
			a[child] = tem;
			parent = child;
			child = parent * 2 + 1;
		}
		//中途child>parent则已满足小堆,直接break
		else
		{
			break;
		}
	}
}

2.3 堆的向上调整算法

使用场景:向堆中插入数据,需要使用向上调整算法调整,因为向堆中插入数据是将数据插入到下标为size的位置,此时就不满足小堆(大堆),因此,需要堆其进行调整,向上调整算法和向下调整算法思路类似,此处以小堆为例,向上调整法只需从插入的节点位置开始和父节点比较,若a[chaild]<a[parent],则交换,若a[chaild]>=a[parent]则说明越界满足小堆,直接break

如下图所示插入一个数据使用向上调整法调整

在这里插入图片描述

2.4 向上调整算法(建小堆)实现

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

2.5 数组建堆算法(建小堆)

若左右子树不是小堆——想办法把左右子树处理成小堆
可以从倒数第一个非叶子节点的位置开始向下调整

如下图所示可以按图中的步骤依次向下调整
最后一个非叶子节点的下标为 (n-1-1)/2

在这里插入图片描述

2.6 数组建堆算法(建小堆)实现

	int n = sizeof(a) / sizeof(int);
	//数组建堆算法
	for (int i = (n - 1 - 1) / 2; i >= 0; --i)
	{
		AdjustDown(arr, n, i);
	}

2.7 堆排序(降序)

下面我们将上面建好的小堆进行降序排序

堆排序(降序)的核心思想:因为建小堆可以选出最小的数即根节点,我们将每次建好的小堆的最后一个叶子节点和根节点进行交换,交换后不把最后一个数看作堆里的数据,此时根的左右子树依旧是大堆,然后我们再用向下调整算法选出次小的如此循环直到堆里剩一个数结束

• 升序建大堆
• 降序建小堆

2.8 堆排序(降序)实现

//降序
void HeapSort(int* a, int n)
{
	//建小堆
	for (int i = (n - 1 - 1) / 2; i >= 0; --i)
	{
		AdjustDown(a, n, i);
	}
	int end = n - 1;
	//把最小的换到最后一个位置,不把最后一个数看作堆里的
	//每次选出剩下数中最小的
	//从后往前放
	while (end > 0)
	{
		int tem = a[end];
		a[end] = a[0];
		a[0] = tem;
		//选出次小的数
		AdjustDown(a, end, 0);
		--end;
	}
}

2.9 建堆的时间复杂度

最坏的情况及满二叉树,且每个节点都需要调整

在这里插入图片描述

由以上推论过程可得建堆的时间复杂度为O(N);
向下调整算法的时间复杂度为O(log2N);
所以堆排序的时间复杂度为O(N*log2N);

到此这篇关于一文学会数据结构-堆的文章就介绍到这了,更多相关堆内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言字符串左旋的两种实现方法

    C语言字符串左旋的两种实现方法

    汇编语言中有一种移位指令叫做循环左移(ROL),下面这篇文章主要给大家介绍了关于C语言字符串左旋的两种实现方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • C 语言基础教程(我的C之旅开始了)[四]

    C 语言基础教程(我的C之旅开始了)[四]

    C 语言基础教程(我的C之旅开始了)[四]...
    2007-02-02
  • VScode配置C语言环境完整版(亲测可用)

    VScode配置C语言环境完整版(亲测可用)

    这篇文章主要介绍了VScode配置C语言环境完整版,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-08-08
  • OpenCV画任意圆弧曲线

    OpenCV画任意圆弧曲线

    这篇文章主要为大家详细介绍了OpenCV画任意圆弧曲线,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • 用c语言实现和平精英的完整代码

    用c语言实现和平精英的完整代码

    这篇文章主要介绍了用c语言实现和平精英的完整代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • C++实现WebSocket服务器的案例分享

    C++实现WebSocket服务器的案例分享

    WebSocket是一种在单个TCP连接上进行全双工通信的通信协议,与HTTP协议不同,它允许服务器主动向客户端发送数据,而不需要客户端明确地请求,本文主要给大家介绍了C++实现WebSocket服务器的案例,需要的朋友可以参考下
    2024-05-05
  • c++与python实现二分查找的原理及实现

    c++与python实现二分查找的原理及实现

    本文介绍了c++与python实现二分查找的原理及实现,二分查找指首先将数组中间值和目标值进行比较,如果相等则返回;如果不相等,则选择中间值左边的一半或者右边的一半进行比较;不断重复直到检索完毕,下文相关资料需要的朋友可以参考一下
    2022-03-03
  • C++实现迷宫算法实例解析

    C++实现迷宫算法实例解析

    这篇文章主要介绍了C++实现迷宫算法实例解析,是一个比较经典的C++算法,有一定的学习与借鉴价值,需要的朋友可以参考下
    2014-07-07
  • 汇编语言rep movsd 的使用详解

    汇编语言rep movsd 的使用详解

    rep movsd 每次ecx!=0便执行movsd ,然后ecx=ecx-1 movsd移动ds:[si] 到es:[di],在32位汇编下可以用esi代替si,edi代替di
    2013-09-09
  • C++实现的大数相乘算法示例

    C++实现的大数相乘算法示例

    这篇文章主要介绍了C++实现的大数相乘算法,结合实例形式分析了C++大数相乘的概念、原理及代码实现技巧,需要的朋友可以参考下
    2017-08-08

最新评论