服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - 一文学会数据结构-堆

一文学会数据结构-堆

2021-12-23 14:40双鱼211 C/C++

本文主要介绍了数据结构-堆,文中通过图片和大量的代码讲解的非常详细,需要学习的朋友可以参考下这篇文章,希望可以帮助到你

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);

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

原文链接:https://blog.csdn.net/weixin_50886514/article/details/114847405

延伸 · 阅读

精彩推荐
  • C/C++深入C++拷贝构造函数的总结详解

    深入C++拷贝构造函数的总结详解

    本篇文章是对C++中拷贝构造函数进行了总结与介绍。需要的朋友参考下...

    C++教程网5182020-11-30
  • C/C++关于C语言中E-R图的详解

    关于C语言中E-R图的详解

    今天小编就为大家分享一篇关于关于C语言中E-R图的详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看...

    Struggler095962021-07-12
  • C/C++c/c++实现获取域名的IP地址

    c/c++实现获取域名的IP地址

    本文给大家汇总介绍了使用c/c++实现获取域名的IP地址的几种方法以及这些方法的核心函数gethostbyname的详细用法,非常的实用,有需要的小伙伴可以参考下...

    C++教程网10262021-03-16
  • C/C++C语言实现双人五子棋游戏

    C语言实现双人五子棋游戏

    这篇文章主要为大家详细介绍了C语言实现双人五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    两片空白7312021-11-12
  • C/C++OpenCV实现拼接图像的简单方法

    OpenCV实现拼接图像的简单方法

    这篇文章主要为大家详细介绍了OpenCV实现拼接图像的简单方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    iteye_183805102021-07-29
  • C/C++使用C++制作简单的web服务器(续)

    使用C++制作简单的web服务器(续)

    本文承接上文《使用C++制作简单的web服务器》,把web服务器做的功能稍微强大些,主要增加的功能是从文件中读取网页并返回给客户端,而不是把网页代码...

    C++教程网5492021-02-22
  • C/C++C语言main函数的三种形式实例详解

    C语言main函数的三种形式实例详解

    这篇文章主要介绍了 C语言main函数的三种形式实例详解的相关资料,需要的朋友可以参考下...

    ieearth6912021-05-16
  • C/C++c/c++内存分配大小实例讲解

    c/c++内存分配大小实例讲解

    在本篇文章里小编给大家整理了一篇关于c/c++内存分配大小实例讲解内容,有需要的朋友们可以跟着学习参考下。...

    jihite5172022-02-22