news 2026/7/13 9:59:30

算法-堆排序

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
算法-堆排序

堆排序 (Heap Sort)

像“选拔赛”一样,每次把数组构造成一个“大顶堆”(保证最顶端是最大值)。然后把冠军(最大值)和队尾的人交换,让他提前“退休”到末尾。接着把剩下的队伍重新调整回大顶堆,再选出新的冠军换到倒数第二个位置。不断重复,队伍就从小到大排好序了。

核心代码

#include <stdio.h> // 堆化函数(向下调整):维护大顶堆的性质 // n 为当前堆的有效长度,i 为当前需要调整的父节点下标 void heapify(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) { int temp = arr[i]; arr[i] = arr[largest]; arr[largest] = temp; heapify(arr, n, largest); // 递归调整受影响的子树 } } // 堆排序函数 void heapSort(int arr[], int n) { // 1. 建堆:从最后一个非叶子节点开始,自底向上调整为大顶堆 for (int i = n / 2 - 1; i >= 0; i--) { heapify(arr, n, i); } // 2. 排序:每次将堆顶(最大值)与末尾元素交换,并缩小堆的范围 for (int i = n - 1; i > 0; i--) { int temp = arr[0]; arr[0] = arr[i]; arr[i] = temp; heapify(arr, i, 0); // 对剩下的 i 个元素重新堆化 } } // 打印数组的辅助函数 void printArray(int arr[], int n) { for (int i = 0; i < n; i++) { printf("%d ", arr[i]); } printf("\n"); } int main() { int arr[] = {64, 34, 25, 12, 22}; int n = sizeof(arr) / sizeof(arr[0]); // 计算数组长度 printf("排序前:"); printArray(arr, n); heapSort(arr, n); // 调用堆排序 printf("排序后:"); printArray(arr, n); return 0; }

示例演示

{64, 34, 25, 12, 22}

第 1 步:构建初始大顶堆
目标:将无序数组调整为父节点大于等于子节点的大顶堆。
最后一个非叶子节点下标为 5/2 - 1 = 1(元素 34)。比较 34 和它的孩子 12、22,无需交换。
处理下标 0(元素 64)。比较 64 和它的孩子 34、25,64 最大,无需交换。
建堆完成,堆顶 64 为全局最大值。
当前数组:[64, 34, 25, 12, 22]

第 2 轮:选出最大值 64
目标:将堆顶 64 与末尾元素 22 交换,并对前 4 个元素重新堆化。
交换 64 和 22,数组变为:[22, 34, 25, 12, | 64]
对 22 进行向下调整:22 的左孩子是 34,右孩子是 25,34 最大,交换 22 和 34。
第 2 轮结束:最大值 64 归位。
当前数组:[34, 22, 25, 12, | 64]

第 3 轮:选出第二大值 34
目标:将堆顶 34 与倒数第二个元素 12 交换,并对前 3 个元素重新堆化。
交换 34 和 12,数组变为:[12, 22, 25, | 34, 64]
对 12 进行向下调整:12 的孩子是 22 和 25,25 最大,交换 12 和 25。
第 3 轮结束:第二大值 34 归位。
当前数组:[25, 22, 12, | 34, 64]

第 4 轮:选出第三大值 25
目标:将堆顶 25 与倒数第三个元素 12 交换,并对前 2 个元素重新堆化。
交换 25 和 12,数组变为:[12, 22, | 25, 34, 64]
对 12 进行向下调整:12 的左孩子是 22,22 > 12,交换 12 和 22。
第 4 轮结束:第三大值 25 归位。
当前数组:[22, 12, | 25, 34, 64]

第 5 轮:选出第四大值 22
目标:将堆顶 22 与倒数第四个元素 12 交换,堆只剩 1 个元素,无需调整。
交换 22 和 12,数组变为:[12, | 22, 25, 34, 64]
排序完成。
最终结果:[12, 22, 25, 34, 64]

复杂度

时间复杂度是\(O(nlogn)\)(建堆耗时\(O(n)\),每次调整堆耗时\(O(logn)\),共调整 n−1 次)
空间复杂度是\(O(1)\)(原地排序,仅需常数级的额外空间用于交换变量)

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

算法-希尔排序

希尔排序 (Shell Sort) 像“分组接力赛”一样&#xff0c;一开始步长(gap)很大&#xff0c;把相隔很远的元素分到一组进行插入排序&#xff0c;让数据能快速跨越到接近最终位置的地方(预排序)&#xff1b;然后不断缩小步长&#xff0c;让数组越来越接近整体有序&#xff1b;最后…

作者头像 李华
网站建设 2026/7/13 9:57:32

C++客户端自动更新系统:从架构设计到工程实现详解

1. 项目概述与核心价值做客户端开发&#xff0c;尤其是桌面端应用&#xff0c;最头疼的问题之一就是版本更新。用户可能分散在全国各地&#xff0c;甚至全球&#xff0c;你不可能指望每个用户都手动去官网下载安装包、覆盖安装。一个稳定、可靠、对用户无感的自动更新系统&…

作者头像 李华
网站建设 2026/7/13 9:56:18

Unity游戏5分钟集成自动翻译:XUnity.AutoTranslator实战指南

1. 项目概述&#xff1a;为什么需要“自动翻译”&#xff1f; 做独立游戏或者小团队开发&#xff0c;最头疼的事情之一可能就是本地化了。你花了好几个月甚至几年时间打磨玩法、优化美术&#xff0c;终于做出了一款自己满意的作品&#xff0c;结果发现海外玩家看不懂你的游戏。…

作者头像 李华