【八大经典排序算法】堆排序

【八大经典排序算法】堆排序


一、概述

堆排序是J.W.J. Williams于1964年提出的。他提出了一种利用堆的数据结构进行排序的算法,并将其称为堆排序。堆排序是基于选择排序的一种改进,通过维护一个堆来选择最大(或最小)的元素,并将其放置在数组的末尾,然后对剩余的元素进行递归调用堆排序。

堆排序在其初期的版本中存在一些性能问题,例如在构建堆的过程中需要频繁的调整堆的结构,导致性能的下降。为了改进这个问题,人们提出了一种称为"堆调整"的操作,将调整堆的过程优化为一次遍历,从而提高了性能。此外,还有一些其他的改进方法,如使用二叉堆来代替普通堆,使用自底向上的构建堆的方法等。

堆排序作为一种经典的排序算法,经过多年的发展与改进,已经成为一种高效稳定的排序算法,并在实际应用中得到广泛的应用。


二、思路解读

我们知道堆排序是一种基于堆数据结构的排序算法,所以堆排序分为以下几步:

①:构建大堆(或小堆)。这里我们从数组的最后一个数据的父节点开始,采用向下调整算法来建堆。

向下调整算法有一个前提:左右子树必须是一个堆,才能调整。同时还要注意是调大堆还是小堆。
调小(大)堆:堆顶元素和孩子中最小(大)的节点比较,如果父节点大于(小于)较小的子节点子,两者交换。不断向下调整到合适位置。(调大堆,和较大孩子比较)

②:将堆中最大(或最小)的元素即堆顶元素与数组中最后一个元素交换位置,然后将堆的大小减1。将交换后的堆顶元素进行向下调整,直到堆再次满足堆性质。

③: 重复上述步骤,直到堆的大小为1,此时整个数组就有序了


三、代码实现(大堆为例)

c 复制代码
void AdjustDown(int* a, int n, int parent)
{
	//建大堆
	int child = parent * 2 + 1;

	while (child < n)
	{
		if (child + 1 < n && a[child + 1] > a[child])
		{
			child++;
		}

		if (a[parent] < a[child])
		{
			Swap(&a[parent], &a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

//堆排序
void HeapSort(int* a, int n)
{
	//升序,建大堆
	for (int i = (n - 2) / 2; i >= 0; i--)
	{
		AdjustDown(a, n, i);
	}

	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		end--;
	}
}

时间复杂度:O(N*logN)
空间复杂度:O(1)


相关推荐
是个西兰花5 分钟前
网络基础1
linux·网络·c++·智能路由器
用户31268748772015 分钟前
线程池到底怎么管理线程的?从 ThreadPoolExecutor 到拒绝策略全链路拆解
java
老赵的博客27 分钟前
c++QT之动态库加载常见报错
c++·qt
cpolar技术支持30 分钟前
Kafka Streams 窗口统计怎么验收:本地跑订单流聚合,用 cpolar 给同事看只读结果页
java·docker·kafka·cpolar·kafka streams
wabs66637 分钟前
关于二叉树【429.N叉树的层序遍历的思考】
数据结构·c++·算法·leetcode·二叉树
爱读源码的大都督38 分钟前
DeepSeek面试官问:生产RAG系统回答不准确,该如何定位和优化?这样回答,能让面试官当场给你Offer!
java·后端·python
hetao173383743 分钟前
2026-09-08 hetao1733837 的刷题记录
c++·算法
码匠许师傅1 小时前
【设计模式精讲】25.状态模式(State)
c++·ui·设计模式·状态模式·uml
C++ 老炮儿的技术栈1 小时前
MFC CPtrArray的用法
开发语言·数据结构·c++·算法·mfc·c
杨运交1 小时前
[069][公共模块]Spring Boot 全局异常处理与参数校验实战(下):校验异常精细化处理与 WebFlux 适配
java·spring boot·后端