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

理解堆排序

堆排序(Heapsort)是一种基于堆这种数据结构的排序算法,但在实际实现中,堆通常是用数组来表示的。这种方法充分利用了数组的特性,使得堆的操作更加高效。下面通过详细解释和举例说明来帮助理解这种排序方式。

堆的数组表示

一个堆是一种完全二叉树,可以通过数组方便地表示:

  • 对于一个节点在数组中的索引i:
    • 它的左子节点的索引是 2*i + 1
    • 它的右子节点的索引是 2*i + 2
    • 其父节点的索引是 (i - 1) // 2

堆排序的步骤

  1. 构建初始堆:将无序数组转化为最大堆或最小堆。这个过程称为“建堆”。

  2. 排序

    • 将堆顶元素(最大值或最小值)与数组的最后一个元素交换。
    • 将堆的大小减一,并对新的堆顶元素执行“堆化”操作,恢复堆的性质。
    • 重复上述步骤,直到堆的大小变为1。

举例说明

假设我们有一个无序数组 [4, 10, 3, 5, 1],我们将用堆排序将它排序。

1. 构建初始堆

首先,我们构建最大堆。调整后的堆如下:

         10/  \5    3/ \4   1

数组表示为 [10, 5, 3, 4, 1]

2. 排序过程
  • 第一步:将堆顶元素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, 1, 5, 10]
  • 第三步:将堆顶元素4与倒数第三个元素1交换,然后调整堆。

    • 交换后数组变为 [1, 3, 4, 5, 10]
    • 调整堆后数组变为 [3, 1, 4, 5, 10]
    • 由于此时堆只有两个元素,因此不需要进一步调整。
  • 第四步:将堆顶元素3与倒数第四个元素1交换,然后调整堆。

    • 交换后数组变为 [1, 3, 4, 5, 10]
    • 调整堆后数组变为 [1, 3, 4, 5, 10]
    • 由于此时堆只有一个元素,因此不需要进一步调整。

最终,数组变为 [1, 3, 4, 5, 10],排序完成。

总结

在堆排序的过程中,虽然我们使用了堆这种数据结构,但实际上,所有的操作都是在数组内部进行的。通过交换数组中的元素,我们在数组上模拟了堆的插入、删除和调整操作。这样,我们可以利用数组的连续内存空间和高效的索引访问特点,同时享受堆数据结构带来的排序优势。

相关文章:

  • Golang中的CAS操作
  • 算法训练营第六十七天 | 卡码网110 字符串接龙、卡码网105 有向图的完全可达性、卡码网106 岛屿的周长
  • 【操作系统】第五章 文件系统
  • odoo的采购询价单,默认情况下显示‘draft‘,‘sent‘,‘purchase‘,请问什么情况下才会显示‘to approve‘?
  • clean code-代码整洁之道 阅读笔记(第十一章)
  • 静态ip详解
  • Android面试题精选——再聊Android-Handler机制
  • 分类接口开发
  • [SAP ABAP] 排序内表数据
  • 计组--存储系统--复习专用...
  • 【iOS】#include、#import、@class、@import
  • 2024广东省职业技能大赛云计算赛项实战——Minio服务搭建
  • CTFHUB-SSRF-端口扫描
  • DDMA信号处理以及数据处理的流程---cfar检测
  • 【database3】oracle:数据交换/存储/收集
  • 【React系列】如何构建React应用程序
  • 【跃迁之路】【463天】刻意练习系列222(2018.05.14)
  • 2019年如何成为全栈工程师?
  • Apache Pulsar 2.1 重磅发布
  • css系列之关于字体的事
  • go语言学习初探(一)
  • nodejs调试方法
  • socket.io+express实现聊天室的思考(三)
  • tab.js分享及浏览器兼容性问题汇总
  • 坑!为什么View.startAnimation不起作用?
  • 区块链技术特点之去中心化特性
  • 如何进阶一名有竞争力的程序员?
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • 小程序测试方案初探
  • 原生Ajax
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • #1015 : KMP算法
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (已解决)vue+element-ui实现个人中心,仿照原神
  • (转)Android学习笔记 --- android任务栈和启动模式
  • **登录+JWT+异常处理+拦截器+ThreadLocal-开发思想与代码实现**
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • .Net Attribute详解(上)-Attribute本质以及一个简单示例
  • .Net Framework 4.x 程序到底运行在哪个 CLR 版本之上
  • .net 程序发生了一个不可捕获的异常
  • .net开发引用程序集提示没有强名称的解决办法
  • .vue文件怎么使用_我在项目中是这样配置Vue的
  • @kafkalistener消费不到消息_消息队列对战之RabbitMq 大战 kafka
  • @select 怎么写存储过程_你知道select语句和update语句分别是怎么执行的吗?
  • [ Linux Audio 篇 ] 音频开发入门基础知识
  • [20161101]rman备份与数据文件变化7.txt
  • [Angular 基础] - 自定义指令,深入学习 directive
  • [C#]winform部署yolov5-onnx模型
  • [C++]打开新世界的大门之C++入门
  • [CISCN2019 华东北赛区]Web2