上一次说到了3种基本的排序算法,三种基本的排序算法时间复杂度都是O(n^2),虽然比较简单,但是效率相对较差,因此后续有许多相应的改进算法,这次主要说说堆排序算法。

堆排序算法是对选择排序的一种优化。

那么什么是堆呢?堆是一种树形结构。在维基百科上的定义是这样的“给定堆中任意节点 P 和 C,若 P 是 C 的母节点,那么 P 的值会小于等于(或大于等于) C 的值”。

这句话通俗一点就是,树的根节点需要大于(小于)它的孩子节点,而每个左右子树都满足这个条件。当树的根节点大于它的左右孩子节点时称为大顶推,否则称为小顶堆。

排序算法的思路是这样的,首先将序列中的元素组织成一个大顶堆,将树的根节点放到序列的最后面,然后将剩余的元素再组织成一个大顶堆,然后放到倒数第二个位置,以此类推。

先假定它们的对应关系如下图所示:

我们从树的最后一个非叶子节点开始,从这个子树中选择最大的一个数,将它交换到子树的根节点,也就是如下图所示

接着再从后往前查找下一个非叶子节点

经过这样一轮,一直调整到树的根节点,让后将根节点放到序列的最后一个元素,接着再将剩余元素重新组织为一个新的堆,直到所有元素都完成排序

现在已经对堆排序的基本思路有了一定的了解,在写代码之前需要建立树节点与它在序列中的相关位置做一个对应关系,假设一个非叶子节点在序列中的位置为n,那么它的两个子节点分别是2n + 1与 2n + 2。而且小于n的一定是位于n前方的非叶子节点,所以在调整堆时,从n开始一直到0,前面的一定是非叶子节点,根据这点可以写出这样的代码

void HeapSort(int a[], int nLength)
{
//从最后一个非叶子节点开始调整
for (int n = nLength / 2 - 1; n >= 0; n--)
{
HeapAdjust(a, n, nLength);
}

for (int n = nLength - 1; n > 0; n--)
{//取堆顶与最后一个叶子节点互换int tmp = a[0];a[0] = a[n];a[n] = tmp;//调整剩余堆HeapAdjust(a, 0, n);
}

}

上述代码首先取最后一个叶子节点,对所有非叶子节点进行调整,得到堆顶的最大元素。然后将最大元素与序列最后一个做交换,接着使用循环,对序列中剩余元素进行同样的操作。

调整堆时,首先比较子树的根节点与它下面的所有子节点,并保存最大数的位置,然后将最大数与根节点的数进行交换,这样一直进行,直到完成了堆根节点的交换。

void HeapAdjust(int a[], int nIdx, int nLength)
{int child = 0; //child 保存当前最大数的下标while (2 * nIdx + 1 < nLength){child = 2 * nIdx + 1;//先找子节点的最大值(保证存在右节点的情况下)if (child < nLength - 1 && a[child] < a[child + 1]){child++;}if (a[nIdx] < a[child]){int tmp = a[nIdx];a[nIdx] = a[child];a[child] = tmp;}else{break;}//如果进行了交换,为了防止对子节点对应子树的破坏,要对子树也进行调整nIdx = child;}
}

从算法上来看,它循环的次数与堆的深度有关,而二叉树的深度应该是log2(n) 向下取整,所以调整的时候需要进行log2(n)次调整,而外层需要从0一直到n - 1的位置每次都需要重组堆并进行调整,所以它的时间复杂度应该为O(nlogn), 它在效率上比选择排序要高,它的速度主要体现在每次查找选择最大的数这个方面。


转载于:https://www.cnblogs.com/lanuage/p/10631371.html

算法与数据结构(六):堆排序相关推荐

  1. 【算法与数据结构】堆排序是什么鬼?

    排序算法相必大家都见过很多种,例如快速排序.归并排序.冒泡排序等等.今天,我们就来简单讲讲堆排序. 在上一篇中,我们讲解了二叉堆,今天的堆排序算法主要就是依赖于二叉堆来完成的,不清楚二叉堆是什么鬼的, ...

  2. 算法与数据结构(六) 迪杰斯特拉算法的最短路径(Swift版)

    上篇博客我们详细的介绍了两种经典的最小生成树的算法,本篇博客我们就来详细的讲一下最短路径的经典算法----迪杰斯特拉算法.首先我们先聊一下什么是最短路径,这个还是比较好理解的.比如我要从北京到济南,而 ...

  3. 浅谈算法和数据结构: 五 优先级队列与堆排序

    原文:浅谈算法和数据结构: 五 优先级队列与堆排序 在很多应用中,我们通常需要按照优先级情况对待处理对象进行处理,比如首先处理优先级最高的对象,然后处理次高的对象.最简单的一个例子就是,在手机上玩游戏 ...

  4. 程序 算法与数据结构

    B-tree(多路搜索树,并不是二叉的)是一种常见的数据结构.使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度.按照翻译,B 通常认为是Balance的简称.这个数据结构一 ...

  5. 算法与数据结构c语言版PPT,C语言算法与数据结构.ppt

    C语言算法与数据结构.ppt 第十二章 算法与数据结构12.1 算法的基本概念,该节知识点所占试题比重为12,属于重点考查对象,基本上每次必考,主要考查算法的定义和对算法复杂度的理解.历次试题分值在0 ...

  6. Caché 算法与数据结构

    第一章 Caché 算法与数据结构 基础和概念 ☆☆☆☆☆ 第二章 Caché 算法与数据结构 数组原理 ☆☆☆☆☆ 第三章 Caché 算法与数据结构 链表原理 ☆☆☆☆☆ 第四章 Caché 算法 ...

  7. 格雷通路 算法 java,Java算法与数据结构教程

    北上广容不下肉身, 三四线放不下灵魂, 程序员里没有穷人, 有一种土豪叫 算法工程师. 程序 = 数据结构 + 算法 程序是为了解决实际问题而存在的.然而为了解决问题,必定会使用到某些数据结构以及设计 ...

  8. 一周刷爆LeetCode,算法da神左神(左程云)耗时100天打造算法与数据结构基础到高级全家桶教程,直击BTAJ等一线大厂必问算法面试题真题详解 笔记

    一周刷爆LeetCode,算法大神左神(左程云)耗时100天打造算法与数据结构基础到高级全家桶教程,直击BTAJ等一线大厂必问算法面试题真题详解 笔记 教程与代码地址 P1 出圈了!讲课之外我们来聊聊 ...

  9. 详解校招算法与数据结构

    算法与数据结构(java)版 一,数据结构 1,数组和链表 (1)数组 数组是最常见的一种数据结构,它是相同类型的用一个标识符封装到一起的基本类型数据序列或者对象序列.数组使用一个统一的数组名和不同的 ...

最新文章

  1. 自动驾驶多模态传感器融合的综述
  2. NSURLSession和NSURLConnection
  3. QT的QQuickImageProvider类的使用
  4. (教学思路 C#集合二)哈希表
  5. React Native使用指南-植入原生应用
  6. Java Lock的使用
  7. Node.js CVE-2017-14849复现(详细步骤)
  8. Linux 6.4 网卡提示 not active怎么办Shutting down interface eth0: Error:
  9. ubunut14.04修改时区,查看版本信息
  10. 机器学习 声音 分角色_机器学习对儿童电视节目角色的痴迷
  11. 指数函数用计算机怎么计算器,万能计算器怎么使用 使用科学计算器方法
  12. python爬虫做灰产_python爬虫
  13. 论文中的Matlab画图常用技巧
  14. 寻找春天nbsp;九宫格日记-2014.04.26
  15. 价值连城的精确短线交易技术--Gartley“222”
  16. VP9编码器客观及主观质量优化
  17. python系列笔记--耗子(巨细)
  18. 朵拉影像开发 冬天真的来了
  19. 每日一佳——Least-Squares Temporal Difference Learning(Justin A. Boyan,ICML,1999)
  20. 每日一思(2022.5.6)——非理性行为

热门文章

  1. node平台的安装与搭建
  2. [算法题] Search in Rotated Sorted Array
  3. mysql 多表 update sql语句总结
  4. 在ASP.NET中调用存储过程方法
  5. 在Project中引用zedgraph控件
  6. CV Code|计算机视觉开源周报20200504期
  7. 地平线开源轻量级、有效可变组卷积的人脸识别网络VarGFaceNet
  8. 如何入门 Python 爬虫?
  9. java都市男人心痒痒_会让男人心痒痒的女人,是懂得套路的
  10. 【OpenCV】OpenCV函数精讲之 -- 多通道图像混合