堆排序详细讲解(C++,默认生成小根堆)

文章目录

  • 一.堆排序初理解⭐
    • 1.1 堆排序的定义
    • 1.2 堆排序基本思想
      • 1.2.1 建堆
      • 1.2.2 堆排序
    • 1.3 复杂度
  • 二.堆排序代码详解⭐
    • 2.1 up()
    • 2.2 down()
    • 主函数

自我介绍:hello!这里是欧_aita的频道,一个初学数据结构与算法的小白。
小欧的今日语录: 每一个裂缝都是为透出光而努力
小欧的祝福语:在代码的海洋中,愿你的航程充满优雅和高效的算法风帆!
大家可以在评论区畅所欲言,可以指出我的错误,在交流中共同进步。
如果你也恰好在学习C++或者数据结构与算法那就来看看主页吧—— 欧_aita。

一.堆排序初理解⭐

1.1 堆排序的定义

堆排序是一种基于二叉堆数据结构的排序算法。它利用了堆的性质来实现对数组的原地排序。堆是一个特殊的树状数据结构,通常分为最大堆和最小堆。在最大堆中,每个节点的值都大于或等于其子节点的值,而在最小堆中,每个节点的值都小于或等于其子节点的值。

1.2 堆排序基本思想

1.2.1 建堆

建堆(Heapify): 将待排序的数组构建成一个二叉堆。这可以通过自底向上地对每个非叶子节点进行堆调整(Heapify)来实现。堆排序详细讲解(C++,默认生成小根堆)_第1张图片

1.2.2 堆排序

堆排序: 将堆顶元素(最大元素或最小元素,取决于是最大堆还是最小堆)与数组末尾元素交换,然后重新调整堆,使得剩余元素重新构成一个堆。重复这个过程,直到整个数组有序。

1.3 复杂度

堆排序的关键在于堆的调整过程,确保每一步都维护堆的性质。堆排序的时间复杂度为 O(n log n),其中 n 是待排序数组的长度。由于堆排序是原地排序算法,空间复杂度为 O(1)。

二.堆排序代码详解⭐

2.1 up()

举个例子,如果我们有一个尚未进行排序处理的二叉树,而我们想要得到的是最小堆,就要对树中每个元素进行判断操作,如果该节点中的子节点有比该节点还小的数据元素,就进行 swap。堆排序详细讲解(C++,默认生成小根堆)_第2张图片

void up(int u)
{
	while (u / 2 && h[u / 2] > h[u])
	{
		swap(h[u / 2], h[u]);
		u /= 2;
	}
}

注意左右两个子节点下标除以2都会是父节点下标。例如根节点的下标为1,他的左孩子节点下标就是2,右孩子节点下标就是3。在u/2是int型,2/2==3/2。所以使用一个判断条件就可以了。

2.2 down()

原理是和up差不多的,但是up是小值向上,但是down是大值向下。

void down(int u)
{
	int t = u;
	if (u * 2 <= S_size && h[u * 2] < h[t])t = u * 2;
	if (u * 2 + 1 <= S_size && h[u * 2 + 1] < h[t])t = u * 2 + 1;
	if (u != t)//不相同表示根节点不是最小值。
	{
		swap(h[u], h[t]);
		down(t);
	}
}

主函数

int main()
{
	scanf("%d%d", &n,&m);
	for (int i = 1; i <= n; i++)scanf("%d", &h[i]);
        S_size = n;

	for (int i = n / 2; i; i++)down(i);

	while (m--)
	{
		printf("%d", h[1]);
		h[1] = h[S_size];
		S_size--;
		down(1);
	}
	return 0;
}

n和m分别代表的是入堆元素个数以及操作次数。
不难发现m是用来消除堆的。

这篇文章就到此为止,如果觉得读完后对你有所帮助的话就点个赞吧,你们的支持是我最大的动力!

你可能感兴趣的:(数据结构与算法,c++,数据结构)