• 今天讲解一下堆排序的原理以及实现、复杂度和稳定性分析


目录

  • 1 堆的定义
  • 2 堆排序的思路
  • 3 代码实现
  • 4 堆的输出(删除操作)
  • 5 堆的插入操作
  • 6 堆排序的特点
  • 7 性能分析

1 堆的定义

堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

定义:
n个关键字序列L[1…n]称为堆,当且仅当该序列满足:

① L(i)>=L(2i) 且 L(i)>=L(2i+1)或

② L(i)<=L(2i) 且 L(i)<=L(2i+1) (1≤isln/2])

可以将该一维数组视为一棵完全二叉树

大根堆:满足条件① 的堆称为大根堆(大顶堆),大根堆的最大元素存放在结点,且其任一非根结点的值小于等于其双亲结点值

对于堆中的元素编号,其实也是逻辑结构映射到数组的一个过程;

小根堆:满足条件2的堆称为小根堆(小顶堆),小根堆的定义刚好相反,结点是最小元素

2 堆排序的思路

首先将存放在L[1…n]中的n个元素建成初始堆,由于堆本身的特点(以大顶堆为例),堆顶元素就是最大值。
输出堆顶元素后,通常将堆底元素送入堆顶,堆被破坏,将堆顶元素向下调整使其继续保持大顶堆的性质,再输出堆顶元素。如此重复。

  • 根据数组构建一个完全二叉树
  • 从最后一个非叶节点开始调整,使得子树成为堆
  • 如此重复,直至满足堆的定义

值得注意的是:

大根堆排序结果为升序

小根堆排序结果为降序

这是一个常见的误区!

这是因为:堆使用的时候都是每次把堆顶的元素干掉留下堆内部的元素做成Top N

如果你要找100000中的 TOP100最大的,你用小根堆

如果你要找100000中的 TOP100最小的,你用大根堆

3 代码实现

void BuildMaxHeap(int *arr,int len)
{// 建立初始大根堆 for(int i = (len-1)/2; i >= 0; i--){HeapAdjust(arr,i,len);}
}// 子树调整
void HeapAdjust(int *arr,int k,int len)
{int temp = arr[k]; // 暂存根节点 for(int i = k*2+1;i < len;i = i*2+1){if (i < len-1 && arr[i] < arr[i+1])i++;if (temp >= arr[i])break; // 筛选结束 else {arr[k] = arr[i];k = i; // 继续向下筛选 }}arr[k] = temp ; // 筛选的值放入最终位置
}void HeapSort(int *arr,int len)
{BuildMaxHeap(arr,len);for(int i = len-1;i > 0;i--){    arr[0] = arr[0] ^ arr[i];  arr[i] = arr[0] ^ arr[i]; arr[0] = arr[0] ^ arr[i];HeapAdjust(arr,0,i);}
}

4 堆的输出(删除操作)

堆中根结点的值肯定是最值,不是最大就是最小,往往需要使用到。

即每次都删除第0个数据(根结点)

那么堆中输出根节点之后如何保证堆原有的特性呢?

删除之后,打破了原有规律,需要调整!

  • 删除根结点

  • 最后一个数据的值赋给根结点

  • 然后再从根结点开始进行一次从上向下的调整


5 堆的插入操作

  • 对堆进行插入操作时,先将新结点放在堆的末端

  • 随后再向上执行调整操作



6 堆排序的特点

堆排序适合关键字较多的情况(如n>1000)
不适合关键字较少的情况
大根堆排序结果为升序
小根堆排序结果为降序

例如,在1千万个数中选出前100个最大值?
首先使用一个大小为100的数组,读入前100个数,建立小顶堆,而后依次读入余下的数,若小于堆顶则舍弃,否则用该数取代堆顶并重新调整堆,待数据读取完毕,堆中100个数即为所求。

7 性能分析

【空间复杂度】:仅使用常数个辅助单元,空间复杂度为 O(1)

【时间复杂度】:建堆时间为 O(n),之后有n-1次向下调整操作,每次调整的时间复杂度为 O(h) h表示树高

故在最好、最坏和平均情况下,堆排序的时间复杂度为 O(nlog2n)

【稳定性】:进行筛选时,有可能把后面相同关键字的元素调整到前面,所以堆排序算法是一种不稳定的排序方法

排序算法 | 堆排序,算法的图解、实现、复杂度和稳定性分析相关推荐

  1. 常见的十种排序算法C++实现(附时空复杂度,稳定性分析)

    本文主要描述排序算法的实现和大体思路,如果大家不了解其中某种算法,可以先去搜索,看看大概流程,再回来看代码就很清晰了. 一.冒泡排序 二.选择排序 三.插入排序 四.希尔排序 五.归并排序 六.快速排 ...

  2. 排序算法 | 快速排序,算法的图解、实现、复杂度和稳定性分析与优化

    今天讲解一下快速排序算法的原理以及实现.复杂度和稳定性分析与优化 目录 1 快速排序的原理 2 快速排序代码实现 3 复杂度和稳定性分析.优化 4 习题练习 1 快速排序的原理 快速排序是所有内部排序 ...

  3. 排序算法 | 直接插入排序算法的图解、实现、复杂度和稳定性分析

    排序算法 | 直接插入排序算法的图解.实现.复杂度和稳定性分析 目录 1.直接插入排序定义 2.直接插入排序,步骤说明 3.动态图演示 4.代码实现,运行结果 5.算法分析 ① 时间复杂度分析 ② 空 ...

  4. 排序算法 | 直接选择排序,算法的图解、实现、复杂度和稳定性分析

    排序算法 | 直接选择排序,算法的图解.实现.复杂度和稳定性分析 目录 1.直接选择排序的原理 2.图解直接选择排序 3.算法代码实现 4.算法复杂度分析.稳定性分析 直接选择排序 1.直接选择排序的 ...

  5. 排序算法 | 希尔shell排序,算法的图解、实现、复杂度和稳定性分析

    希尔shell排序 1.希尔排序--定义 2.希尔排序--步骤描述 3.希尔排序--算法实现 4.希尔排序--复杂度.稳定性分析 1.希尔排序--定义 希尔排序按其设计者希尔(Donald Shell ...

  6. 排序算法 | 简单选择排序,算法的图解、实现、复杂度和稳定性分析

    今天讲解一下简单选择排序的原理以及实现.复杂度和稳定性分析 这个内容很简单,轻松加愉快,很快就过了~ 目录 简单选择排序 1 基本思想 2 动态图解 3 代码 4 复杂度分析 简单选择排序 1 基本思 ...

  7. C++实现各种排序以及复杂度,稳定性分析

    代码如下: #include<iostream> using namespace std;void Bubble_Sort(int *a, int n) {bool flag;int tm ...

  8. C++ 十大经典排序算法原理及模板之STL方法实现以及稳定性分析

    写在前面: 1.本文中默认排序为升序,降序的原理类似. 2.如果程序直接复制到vs出现无法识别标记的问题,解决方法在这:vs无法识别标记的解决方法 3.本文的算法都是自己用stl实现的,疏漏之处还请指 ...

  9. 希尔排序实现与复杂度、稳定性分析

    import java.util.*;public class ShellSort {public int[] shellSort(int[] a, int n) {//先判断条件if(a== nul ...

最新文章

  1. Debain 安装ssh
  2. python报错怎么看_python中的错误如何查看
  3. 使用MySQL的存储过程
  4. Adobe illustrator 拼图模板制作 - 连载21
  5. 耿丹16-1第一次作业
  6. 游戏开发之C++多继承及虚继承(C++基础)
  7. 分辨率_电视分辨率多少合适
  8. rufus制作UOS启动盘报syslinux-6.03下载错误
  9. 【电场】基于模拟电荷法计算输电线路铁塔周围电场分布附matlab代码
  10. socket 读、写字节流数据
  11. 产品线管理:学习笔记
  12. 对话窗口、面板滚动视图、标签切换视图;QDialog、QScroollArea、
  13. 百度经纬度和google经纬度转换测试
  14. pip升级失败,pip拒绝访问
  15. 三人表决器与八人抢答器实验
  16. 剖析G1(Garbage First)
  17. 描写妙龄少女句子赏析
  18. IntelliJ IDEA创建第一个Vue工程
  19. Oracle之ADG与DG的区别?
  20. KMSAuto Net工具的正确使用方法

热门文章

  1. Bitcoin0.21版 公链开发(3) 网关PHP windows上安装
  2. [计算机网络] 【谢希仁】考前突击复习二、三、四章
  3. 【AI出牌器】第一次见这么“刺激”的斗地主,胜率高的关键因素竟是......
  4. optee的共享内存的介绍
  5. boot.img详解
  6. Prison Architect 64位逃脱模式穿墙代码
  7. 2020-11-11(对话框简单总结)
  8. vbs发送邮件(win10环境下成功)
  9. 2.内核异常处理流程
  10. 字典数组根据某key排序