当前位置: 首页 > news >正文

堆排序算法

时间复杂度稳定:始终为O(n log n)

空间效率高:原地排序,O(1)额外空间

适用于大数据集:不会出现快速排序的最坏情况

实现相对简单:基于简单的堆操作


前言

 什么是堆排序?

堆排序(Heap Sort)是一种基于二叉堆数据结构的比较排序算法,具有O(n log n)的时间复杂度和O(1)的空间复杂度,是一种高效的原地排序算法


堆的定义

二叉堆是一种特殊的完全二叉树,满足以下性质:

最大堆:每个节点的值都大于或等于其子节点的值

最小堆:每个节点的值都小于或等于其子节点的值

堆的数组表示

堆可以用数组来表示,具有以下索引关系:父节点索引:parent(i) = (i-1)/2,左子节点:left(i) = 2*i + 1,右子节点:right(i) = 2*i + 2;假如数组为[16, 14, 10, 8, 7, 9]

堆排序算法步骤

堆排序分为两个主要阶段:

构建最大堆(Build Max Heap)

将无序数组构建成最大堆。

 排序阶段(Heap Sort)

将堆顶元素(最大值)与最后一个元素交换减少堆的大小对新的堆顶元素进行堆化(Heapify)重复上述过程直到堆大小为1;

核心算法:堆化(Heapify)

堆化是维护堆性质的关键操作,其时间复杂度为O(log n)

// 维护最大堆性质
void heapify(vector<int>& arr, int n, int i) {int largest=i;int left=2*i+1;int right=2*i+2;if(left<n&&arr[left]>arr[largest])largest=left;if(right<n&&arr[right]>arr[largest])largest=right;if(largest!=i){swap(arr[i],arr[largest]);heapify(arr,n,largest);}}
}

完整的代码实现

#include <iostream>
#include <vector>
using namespace std;// 堆化函数:维护最大堆性质
void heapify(vector<int>& arr, int n, int i) {int largest = i;        // 初始化最大值为根节点int left = 2 * i + 1;   // 左子节点int right = 2 * i + 2;  // 右子节点// 如果左子节点存在且大于根节点if (left < n && arr[left] > arr[largest])largest = left;// 如果右子节点存在且大于当前最大值if (right < n && arr[right] > arr[largest])largest = right;// 如果最大值不是根节点if (largest != i) {swap(arr[i], arr[largest]);// 递归堆化受影响的子树heapify(arr, n, largest);}
}// 堆排序主函数
void heapSort(vector<int>& arr) {int n = arr.size();// 构建最大堆(从最后一个非叶子节点开始)for (int i = n / 2 - 1; i >= 0; i--)heapify(arr, n, i);// 逐个提取元素for (int i = n - 1; i > 0; i--) {// 将当前最大值(堆顶)移到数组末尾swap(arr[0], arr[i]);// 对剩余元素重新堆化heapify(arr, i, 0);}
}// 测试函数
int main() {vector<int> arr = {12, 11, 13, 5, 6, 7};cout << "原始数组: ";for (int num : arr) cout << num << " ";cout << endl;heapSort(arr);cout << "排序后数组: ";for (int num : arr) cout << num << " ";cout << endl;return 0;
}
原始数组: 4 10 3 5 1
堆化索引1(值10): 4/ \10  3/ \
5   1堆化索引0(值4):4        → 交换4和10 →  10/ \                    / \10  3                  4   3/ \                    / \
5   1                  5   1继续堆化:    10  → 交换4和5 →    10/ \                 / \4   3               5   3/ \                 / \5   1               4   1最终最大堆: [10, 5, 3, 4, 1]
交换堆顶10和末尾1: [1, 5, 3, 4, 10]
堆化: [5, 4, 3, 1, 10]
交换堆顶5和末尾1: [1, 4, 3, 5, 10]
堆化: [4, 1, 3, 5, 10]
交换堆顶4和末尾3: [3, 1, 4, 5, 10]
堆化: [3, 1, 4, 5, 10]
交换堆顶3和末尾1: [1, 3, 4, 5, 10]

堆排序的特点

优点时间复杂度稳定为O(n log n)原地排序,空间效率高对于大数据集表现良好缺点:不稳定排序(相同元素可能改变相对顺序)缓存不友好(访问模式不连续)常数因子较大,小数据集不如插入排序快


总结

堆排序是一种高效、原地、基于比较的排序算法,具有稳定的O(n log n)时间复杂度。虽然在实际应用中由于缓存不友好和较大的常数因子,它可能不如快速排序快,但在某些特定场景(如需要保证最坏情况性能或空间受限环境)下,堆排序仍然是很好的选择。


文章转载自:

http://6I3YxM4s.jnbsx.cn
http://jyLlj5pR.jnbsx.cn
http://qY0fWkQB.jnbsx.cn
http://lkawoF9A.jnbsx.cn
http://1qtj4kk8.jnbsx.cn
http://1QVqflal.jnbsx.cn
http://hNERD6mB.jnbsx.cn
http://SUiJlvXQ.jnbsx.cn
http://hsCmpCF4.jnbsx.cn
http://oTcxRcXv.jnbsx.cn
http://lh7pWiDQ.jnbsx.cn
http://6JaOXCYE.jnbsx.cn
http://1fcz7goF.jnbsx.cn
http://4o8nGOwi.jnbsx.cn
http://gYYj1DYZ.jnbsx.cn
http://lP6WNeBn.jnbsx.cn
http://7gHisGo1.jnbsx.cn
http://uGdhP10B.jnbsx.cn
http://D6O7njge.jnbsx.cn
http://ySUGFvxF.jnbsx.cn
http://WMrSWHuL.jnbsx.cn
http://VtJE8G0R.jnbsx.cn
http://lJRKjHvq.jnbsx.cn
http://bEmggY8Q.jnbsx.cn
http://tCim4ehO.jnbsx.cn
http://zxFU6tXM.jnbsx.cn
http://WfWwErj6.jnbsx.cn
http://7nWCIcEA.jnbsx.cn
http://nNcEXpbI.jnbsx.cn
http://UNMULyK3.jnbsx.cn
http://www.dtcms.com/a/388378.html

相关文章:

  • 安卓多任务闹钟实现
  • 【源码集锦】基于Java+SpringBoot+Uniapp+Mysql的租房小程序技术搭建
  • Oceanbase下使用TPC-H模式生成数据
  • 20250917让荣品RD-RK3588-MID开发板的Android13系统在刷机的时候就直接以百分比显示电池电量
  • MySQL 核心操作全解析(用户 + SHOW+DML+DCL)
  • 【前端】【React】【Zustand】[特殊字符] Zustand 系统学习大纲(实战版)
  • 在测试接口时,遇到关于时间参数的传参时,遇到类型编译器无法转换的解决方案
  • 晶圆厂为什么都采用高架地板?
  • unsloth 笔记:微调mistral-7b(纯文本数据集)
  • 【vim,Svelte】怎样使用 vim 编辑 Svelte 那些奇奇怪怪名字的文件?
  • 【AOI基板外观缺陷检测软件】基于Halcon+C#开发的AOI基板外观缺陷检测软件,全套源码,开箱即用
  • htb academy笔记-module-Password Attacks(一)
  • Java程序设计:顺序结构与分支结构
  • 铺满式水印添加教程!水印如何铺满整个详情页页面?
  • 基于SpringBoot+Vue.js开发的医疗器械管理系统
  • 职业定位:用 “能力 - 兴趣 - 需求” 模型找到赛道
  • Caffeine Expiry
  • 【C++项目】C++11重构muduo库
  • 如何选择靠谱的防伪溯源系统公司?
  • 线程池 相关知识
  • 搭建CI/CD 流水线简单说明
  • 大Key与热Key详解:概念、危害与解决方案
  • Java中的自动拆装箱原理
  • Android 入门笔记(2)
  • 程序员内功之成长性思维
  • vLLM 和 SGLang 是两个近年来备受关注的开源项目
  • CMake进阶: 路径处理指令join_paths和cmake_path
  • 算法简略速记手册
  • C语言(长期更新)第17讲内存函数
  • 【CSP-S】 基础知识与编程环境