堆排序包括两个阶段,初始化建堆和重建堆。所以堆排序的时间复杂度由这两方面组成,下面分别进行分析。先post一个实现代码,便于分析。

#include <stdio.h>void swap(int *a, int *b);
void adjustHeap(int param1,int j, int inNums[]);
void  HeapSort(int nums, int inNums[]);
//大根堆进行调整
void adjustHeap(int param1, int j, int inNums[])
{int temp=inNums[param1];for (int k=param1*2+1;k<j;k=k*2+1){//如果右边值大于左边值,指向右边if (k+1<j && inNums[k]< inNums[k+1]){k++;}//如果子节点大于父节点,将子节点值赋给父节点,并以新的子节点作为父节点(不用进行交换)if (inNums[k]>temp){inNums[param1]=inNums[k];param1=k;}elsebreak;}//put the value in the final positioninNums[param1]=temp;
}
//堆排序主要算法
void HeapSort(int nums,int inNums[])
{//1.构建大顶堆for (int i=nums/2-1;i>=0;i--){//put the value in the final positionadjustHeap(i,nums,inNums);}//2.调整堆结构+交换堆顶元素与末尾元素for (int j=nums-1;j>0;j--){//堆顶元素和末尾元素进行交换int temp=inNums[0];inNums[0]=inNums[j];inNums[j]=temp;adjustHeap(0,j,inNums);//重新对堆进行调整}
}
int main() {int data[] = {6,5,8,4,7,9,1,3,2};int len = sizeof(data) / sizeof(int);HeapSort(len,data);return 0;
}

一.初始化建堆

  初始化建堆只需要对二叉树的非叶子节点调用adjusthead()函数,由下至上,由右至左选取非叶子节点来调用adjusthead()函数。那么倒数第二层的最右边的非叶子节点就是最后一个非叶子结点。
  假设高度为k,则从倒数第二层右边的节点开始,这一层的节点都要执行子节点比较然后交换(如果顺序是对的就不用交换);倒数第三层呢,则会选择其子节点进行比较和交换,如果没交换就可以不用再执行下去了。如果交换了,那么又要选择一支子树进行比较和交换;高层也是这样逐渐递归。
  那么总的时间计算为:s = 2^( i - 1 ) * ( k - i );其中 i 表示第几层,2^( i - 1) 表示该层上有多少个元素,( k - i) 表示子树上要下调比较的次数。
  S = 2^(k-2) * 1 + 2^(k-3)2…..+2(k-2)+2^(0)*(k-1) ===> 因为叶子层不用交换,所以i从 k-1 开始到 1;
  S = 2^k -k -1;又因为k为完全二叉树的深度,而log(n) =k,把此式带入;
  得到:S = n - log(n) -1,所以时间复杂度为:O(n)

二.排序重建堆

  在取出堆顶点放到对应位置并把原堆的最后一个节点填充到堆顶点之后,需要对堆进行重建,只需要对堆的顶点调用adjustheap()函数。
  每次重建意味着有一个节点出堆,所以需要将堆的容量减一。adjustheap()函数的时间复杂度k=log(n),k为堆的层数。所以在每次重建时,随着堆的容量的减小,层数会下降,函数时间复杂度会变化。重建堆一共需要n-1次循环,每次循环的比较次数为log(i),则相加为:log2+log3+…+log(n-1)+log(n)≈log(n!)。可以证明log(n!)和nlog(n)是同阶函数:
  ∵(n/2)n/2≤n!≤nn,∵(n/2)n/2≤n!≤nn,
  ∴n/4log(n)=n/2log(n1/2)≤n/2log(n/2)≤log(n!)≤nlog(n)∴n/4log⁡(n)=n/2log⁡(n1/2)≤n/2log⁡(n/2)≤log⁡(n!)≤nlog⁡(n)
  所以时间复杂度为O(nlogn)

三.总结

  初始化建堆的时间复杂度为O(n),排序重建堆的时间复杂度为nlog(n),所以总的时间复杂度为O(n+nlogn)=O(nlogn)。另外堆排序的比较次数和序列的初始状态有关,但只是在序列初始状态为堆的情况下比较次数显著减少,在序列有序或逆序的情况下比较次数不会发生明显变化。

堆排序的时间复杂度分析相关推荐

  1. 堆排序的python实现及时间复杂度分析

    堆是一种形如二叉树的抽象数据结构,要求根节点的元素大于(小于)左右子树的节点,左右子树也需满足上述条件,是一种递归定义. 堆排序的python实现,主要分为两大部分: 1.根据原始数组建立初始堆,只需 ...

  2. 数据结构:堆的实现与建堆时间复杂度分析

    目录 前言 一.堆的介绍 1.堆的本质 2.堆的分类 二.堆的实现(以小根堆为例) 1.关于二叉树的两组重要结论: 2.堆的物理存储结构框架(动态数组的简单构建) 3. 堆元素插入接口(以小根堆为例) ...

  3. 排序算法时间复杂度分析

    排序算法中比较次数与初始元素序列排序无关的只有选择排序和基数排序,其他的都有关.元素的移动次数与关键字的初始排列次序无关的是:基数排序 元素的比较次数与初始序列无关是:选择排序.折半插入排序 算法的时 ...

  4. 归并排序执行次数_归并排序过程、时间复杂度分析及改进

    前言 上一篇文章,介绍过第一种基于分治策略的排序算法--快速排序.接下来我们来讨论另一种基于分治策略的排序算法,归并排序.归并排序也被认为是一种时间复杂度最优的算法,我们还是按照基本过程,代码,最坏时 ...

  5. 算法时间复杂度分析基础

    摘要       本文论述了在算法分析领域一个重要问题--时间复杂度分析的基础内容.本文将首先明确时间复杂度的意义,而后以形式化方式论述其在数学上的定义及相关推导.从而帮助大家从本质上认清这个概念. ...

  6. 快速排序 C++代码实现及其算法思想及时间复杂度分析及优化 恋上数据结构笔记

    文章目录 复习梗概 算法思想 算法复杂度分析及稳定性 如何优化? 快速排序改进版代码C++ 快速排序个人青春版代码 完整代码 复习梗概 算法思想,别的排序名字直接就能让人联想到它的算法思想,唯独快速排 ...

  7. 快速排序的时间复杂度分析

    快速排序的时间复杂度分析 先说结论: 最坏情况:O(N2)O(N^{2})O(N2) 最好情况和平均情况:O(NlogN)O(NlogN)O(NlogN) 下面开始分析. 假设一个序列共有 N 个元素 ...

  8. BZOJ 3277 串 BZOJ 3473 字符串 (广义后缀自动机、时间复杂度分析、启发式合并、线段树合并、主席树)...

    标签那么长是因为做法太多了... 题目链接: (bzoj 3277) https://www.lydsy.com/JudgeOnline/problem.php?id=3277 (bzoj 3473) ...

  9. BZOJ 3277 串 BZOJ 3473 字符串 (广义后缀自动机、时间复杂度分析)

    标签那么长是因为做法太多了... 题目链接: (bzoj 3277) https://www.lydsy.com/JudgeOnline/problem.php?id=3277 (bzoj 3473) ...

最新文章

  1. 苏黎世华人博士提出模型SwinIR,只用33%的参数量就碾压图像修复领域sota
  2. 继续VISTA下网卡驱动问题
  3. 设计模式之单件模式(Singleton Pattern)
  4. 不能头脑一热,就布局颠覆性技术、上马未来产业
  5. 互联网 | 逻辑上的黑话才是真正的花里胡哨
  6. (16)FPGA面试技能提升篇(Python)
  7. linux tab的含义,理解Linux中crontab定时器里的 21 含义 - 金牛座, 爬山虎, PHPCreeper, Workerman, Swoole, PHP爬虫引擎, PHP爬...
  8. kernel编译报错问题kernel is not clean, please run 'make mrproper'
  9. JS中的!=、== 、!==、=== 的用法和区别
  10. matlab三边定位算法,利用matlab分别对三边测量定位算法和改进算法进行仿真和验证...
  11. 【机器学习】实验5布置:基于K-近邻的车牌号识别
  12. 物联网安全 - 对称加密算法
  13. 高等数学—常见三角函数
  14. IEEE ICIP 2019 | 更快更好的联邦学习:一种特征融合方法
  15. ElasticSearch索引基本操作POST PUT GET DELETE
  16. vue之vue的生命周期、swiper、自定义组件的封装、自定义指令、过滤器、单文件组件及vue-cli
  17. 智能手机防盗软件测试自学,用谁找回手机几率最大?手机防盗软件功能大PK
  18. layui框架下拉选择树性图(转载)
  19. 怎么选择好用的超级浏览器?
  20. 大数据Hadoop(一)

热门文章

  1. 关于document.referrer的使用需要注意
  2. BNU 26349——Cards——————【区间dp】
  3. 位向量 补码与无符号 加法与乘法 CSAPP学习笔记
  4. 深圳科技园血案:程序员砍杀产品经理
  5. 实用的SqlHelper类
  6. [原创 URL重写步骤
  7. PHP+AJAX 投票器功能
  8. 对于一颗具有n个结点,度为4的树来说,( )
  9. 2018年第九届蓝桥杯C/C++ A组国赛 —— 第四题:约瑟夫环
  10. 信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言—— 1050:骑车与走路