堆排序精讲

简介: 堆排序精讲

堆排序的时间复杂度是n*logn,可以说吊打冒泡排序(n^2)。是建立在堆这种数据结构的理解上演化出来的一种排序方式。上篇文章对堆这种数据结构已经有详细的介绍。这篇文章就用堆这种数据结构基础搞定堆排序。

一.堆排序思路

堆排序的思路是:若排降序,将给定数据(数组中)建小堆,因为小堆堆顶数据一定最小,每次互换堆顶元素和最后一个元素,将最后一个元素分隔开,然后从堆顶开始向下调整,继续互换堆顶元素和倒数第二个元素,再将倒数第二个分隔开,再从堆顶向下调整,循环这个过程,直到只剩下一个元素为止。若排升序,则建大堆,后续相同。

二.建堆

堆的存储结构是数组,逻辑结构是完全二叉树。要想实现堆排序,首先需要建堆这里提供两种建堆方法:

一.向下调整建堆

first step,找到尾节点的父亲节点

注:灰色数字为数组中的下标

second step,从这个节点开始向下调整,下标顺序为:3->2->1->0

注:红色的数字为向下调整顺序:1->2->3->4

二.向上调整建堆

向下调整建堆的本质就是依次将数据插入堆

插入顺序为:1->2->3->4->5->6->7->8

每次向上调整,将数据一个一个插入堆。可保证最后是一个堆。

三.排序(这里是降序)

降序需要建小堆,排序的逻辑就是每次交换堆顶元素和堆尾(下标为end)元素,分离堆尾元素。

交换完毕后,将堆顶元素向下调整,重新建堆,堆顶元素又成为剩下数据中的最小数据,再交换堆顶元素和堆尾元素(下标为end),再分离,循环往复,直到堆里只整下一个元素。

四.代码实现及测试

1. void swap(int* pa, int* pb)//交换函数
2. {
3.  int tmp = *pa;
4.  *pa = *pb;
5.  *pb = tmp;
6. }
7. void AdjustDown(int* a, int size, int parent)//建小堆的向下调整
8. {
9.  int child = parent * 2 + 1;//左孩子
10.   while (child<size)
11.   {
12.     if (child+1<size&&a[child] > a[child + 1])//找到较小的孩子
13.       child++;
14. 
15.     if (a[parent] >a[child])
16.     {
17.       swap(&a[parent], &a[child]);
18.       parent = child;
19.       child = parent * 2 + 1;
20.     }
21.     else
22.       break;
23.   }
24. }
25. int main()
26. {
27.   int a[7] = {2,4,5,7,6,8,9};//想要排降序
28.   //建小堆
29.   int end = 6;//堆尾下标
30.   int parent = (end - 1) / 2;//堆尾节点的父亲节点下标
31.   while (parent >= 0)
32.   {
33.     AdjustDown(a, 7, parent);//这里用向下调整建堆
34.     parent--;
35.   }
36. //排序
37.   while (end > 0)//直到堆里只剩下最后一个数据
38.   {
39.     swap(&a[0], &a[end]);
40.     AdjustDown(a, end, 0);
41.     end--;
42.   }
43. //测试
44.   for (int i = 0; i < 7; i++)
45.   {
46.     printf("%d ", a[i]);
47.   }
48.   return 0;
49. }

代码测试结果


相关文章
|
2月前
|
人工智能 搜索推荐 机器人
智能体是什么?3 分钟读懂 AI 智能体核心能力与应用场景
AI 智能体是具备自主理解、决策、执行任务能力的新一代 AI 系统,区别于传统 “指令响应式” 工具,它能像人类搭档一样拆解复杂需求、联动多能力模块完成闭环工作。NuwaAI 作为智能体数字人领域的标杆产品,已实现 “一句话生成智能体数字人”,其独创的双脑架构可支撑教育培训、电商直播、文旅表演、企业服务等 8 大场景,帮助用户将表达力转化为生产力,实测能降低 80% 的重复工作人力成本(数据来源:2025 年 AI 智能体行业白皮书)。
|
Oracle 关系型数据库 MySQL
MySQL复制表结构create table as与like的区别
MySQL复制表结构create table as与like的区别
525 0
第k小的数(2种快排解法、1种堆排解法)
第k小的数(2种快排解法、1种堆排解法)
335 0
|
安全 C++
【C++11保姆级教程】移动构造函数(move constructor)和移动赋值操作符(move assignment operator)
【C++11保姆级教程】移动构造函数(move constructor)和移动赋值操作符(move assignment operator)
1846 0
|
存储 算法 Linux
【Linux系统编程】Linux 文件系统探究:深入理解 struct dirent、DIR 和 struct stat结构
【Linux系统编程】Linux 文件系统探究:深入理解 struct dirent、DIR 和 struct stat结构
874 0
|
存储 Linux C语言
(2)Qt中的字符串类型
本文介绍了Qt中的字符串类型QByteArray和QString,包括它们的构造函数、数据操作方法、查找操作、遍历操作以及与其他类型之间的转换,并解释了它们之间的区别。
882 5
(2)Qt中的字符串类型
|
数据库 索引
数据结构中平衡二叉树插入删除中左旋、右旋、左右双旋、右左双旋的详解(题目讲解 简单易懂)
数据结构中平衡二叉树插入删除中左旋、右旋、左右双旋、右左双旋的详解(题目讲解 简单易懂)
676 0
|
存储 算法 C语言
C语言手撕实战代码_循环单链表和循环双链表
本文档详细介绍了用C语言实现循环单链表和循环双链表的相关算法。包括循环单链表的建立、逆转、左移、拆分及合并等操作;以及双链表的建立、遍历、排序和循环双链表的重组。通过具体示例和代码片段,展示了每种算法的实现思路与步骤,帮助读者深入理解并掌握这些数据结构的基本操作方法。
423 2
|
C语言
C语言(14)----柔性数组
C语言(14)----柔性数组
221 1
|
存储 编译器 C语言
C语言程序设计——字符输入函数getchar()
C语言程序设计——字符输入函数getchar()

热门文章

最新文章