news 2026/3/17 16:07:07

堆排序的核心思想是利用堆这种特殊的完全二叉树结构进行排序,其中大根堆要求父节点的值不小于其子节点的值

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
堆排序的核心思想是利用堆这种特殊的完全二叉树结构进行排序,其中大根堆要求父节点的值不小于其子节点的值

堆排序的核心思想是利用堆这种特殊的完全二叉树结构进行排序,其中大根堆要求父节点的值不小于其子节点的值,从而保证堆顶元素为当前堆中的最大值。以下是基于序列 (55,60,40,10,80,65,15,5,75) 实现堆排序中“交换堆顶与末尾元素、调整堆”的核心循环逻辑的代码片段:

defheapify(arr,n,i):"""调整以 i 为根的子树为大根堆"""largest=i# 初始化最大值为根节点left=2*i+1# 左子节点right=2*i+2# 右子节点# 如果左子节点存在且大于根ifleft<nandarr[left]>arr[largest]:largest=left# 如果右子节点存在且大于当前最大值ifright<nandarr[right]>arr[largest]:largest=right# 如果最大值不是根节点,则交换并继续调整iflargest!=i:arr[i],arr[largest]=arr[largest],arr[i]heapify(arr,n,largest)# 递归调整受影响的子树defheap_sort(arr):"""堆排序主函数"""n=len(arr)# 构建大根堆(从最后一个非叶子节点开始向上调整)foriinrange(n//2-1,-1,-1):heapify(arr,n,i)# 逐个提取堆顶元素(最大值)放到数组末尾foriinrange(n-1,0,-1):arr[0],arr[i]=arr[i],arr[0]# 交换堆顶与末尾heapify(arr,i,0)# 对剩余元素重新调整为大根堆# 示例使用data=[55,60,40,10,80,65,15,5,75]print("原始序列:",data)heap_sort(data)print("排序后序列:",data)

输出结果:

原始序列: [55, 60, 40, 10, 80, 65, 15, 5, 75] 排序后序列: [5, 10, 15, 40, 55, 60, 65, 75, 80]

算法说明:

  • 构建堆:从最后一个非叶子节点n//2 - 1开始,逆序向前对每个节点调用heapify,确保整个数组满足大根堆性质。
  • 排序过程:将堆顶(最大值)与末尾元素交换,然后对前i个元素再次调用heapify恢复堆结构,重复此过程直到全部有序。
  • 时间复杂度:建堆 O(n),每次调整 O(logn),共 n-1 次调整 → 总体O(n log n)
  • 空间复杂度:仅使用常数额外空间 →O(1)
  • 稳定性:由于父子节点间跳跃式交换,相同元素相对位置可能改变 →不稳定排序
  • 在堆排序中,堆是一棵完全二叉树。对于一个长度为n的数组,其对应的完全二叉树的最后一个非叶子节点是最后一个节点的父节点

由于完全二叉树的性质:

  • 数组下标从 0 开始;
  • 对于任意节点索引i,其左子节点为2*i + 1,右子节点为2*i + 2
  • 反之,任意节点i的父节点索引为(i - 1) // 2

最后一个节点的索引是n - 1,因此它的父节点就是最后一个非叶子节点:

last_non_leaf_index=(n-1-1)//2=(n-2)//2

但更简单且常用的方式是从最后一个有子节点的节点推导:
我们知道,如果某个节点i满足2*i + 1 < n,则它是非叶子节点。要找最大的这样的i

实际上,最后一个非叶子节点的索引为:

last_non_leaf=⌊n2⌋−1 \text{last\_non\_leaf} = \left\lfloor \frac{n}{2} \right\rfloor - 1last_non_leaf=2n1

示例验证:

数组长度n = 9(如序列 [55,60,…,75])
则最后一个非叶子节点索引为:
9//2−1=4−1=3 9 // 2 - 1 = 4 - 1 = 39//21=41=3

即索引 3 的元素(值为 10)是最后一个非叶子节点。它有两个子节点:

  • 左子:2*3+1 = 7→ arr[7] = 5
  • 右子:2*3+2 = 8→ arr[8] = 75

再往后,索引 4 到 8 都是叶子节点(无需调整)。

结论:

✅ 所以,在堆排序中,构建堆时应从索引n//2 - 1开始,逆序遍历到 0,依次对每个非叶子节点调用heapify

foriinrange(n//2-1,-1,-1):heapify(arr,n,i)

这是正确且高效的建堆顺序。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/15 20:12:02

仅限内部分享:大型项目中C#通信拦截器的10个关键应用场景

第一章&#xff1a;C#网络通信拦截器的核心机制C#网络通信拦截器是实现高级网络控制与调试的关键组件&#xff0c;广泛应用于API监控、安全检测和性能分析场景。其核心机制依赖于对底层Socket通信的透明代理或Hook技术&#xff0c;通过重定向数据流来捕获、修改甚至阻断网络请求…

作者头像 李华
网站建设 2026/3/15 16:25:16

C#企业级模块划分实战指南(99%工程师忽略的关键设计点)

第一章&#xff1a;C#企业级模块划分的核心理念在构建大型C#应用程序时&#xff0c;合理的模块划分是确保系统可维护性、可扩展性和团队协作效率的关键。良好的模块设计不仅能够降低代码耦合度&#xff0c;还能提升单元测试的覆盖率和部署的灵活性。关注点分离 将系统按业务功能…

作者头像 李华
网站建设 2026/3/15 16:07:49

健身房会员卡识别:新用户注册时快速导入旧卡信息

健身房会员卡识别&#xff1a;新用户注册时快速导入旧卡信息 在健身房前台&#xff0c;一位刚搬来本地的会员正准备注册新账户。他掏出一张略显磨损的旧会员卡&#xff0c;工作人员接过卡片、打开系统、准备手动录入信息——姓名、手机号、卡号、有效期……不到十个字段&#x…

作者头像 李华
网站建设 2026/3/15 16:07:49

校园安全管理:学生出入登记表OCR识别留存电子档案

校园安全管理&#xff1a;学生出入登记表OCR识别留存电子档案 在一所普通中学的门卫室里&#xff0c;每天清晨和傍晚总能看到这样一幕&#xff1a;值班老师戴着老花镜&#xff0c;低头翻看一张张字迹各异的纸质《学生出入登记表》&#xff0c;然后手动将“张三、高三&#xff0…

作者头像 李华
网站建设 2026/3/15 16:08:13

盲人辅助阅读:手机拍摄书籍页面实时语音朗读OCR结果

盲人辅助阅读&#xff1a;手机拍摄书籍页面实时语音朗读OCR结果 在一间安静的图书馆里&#xff0c;一位视障学生举起手机&#xff0c;对准摊开的物理教材轻轻一拍。不到三秒后&#xff0c;耳机中传来清晰的人声&#xff1a;“麦克斯韦方程组描述了电场与磁场之间的关系……”没…

作者头像 李华
网站建设 2026/3/15 16:07:51

java计算机毕业设计学术团队资源管理系统 高校科研协作与资产一体化平台 基于SpringBoot的学术团队协同与资源共享系统

计算机毕业设计学术团队资源管理系统360369&#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。在“双一流”建设背景下&#xff0c;科研资源的碎片化、信息孤岛化已成为制约高校学术…

作者头像 李华