堆排序

定义

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

稳定性

不稳定

时间复杂度

O(N*logN)

建堆方法

HeapInsert 上浮

描述

假定事先不知道有多少个元素,通过不断往堆里面插入元素进行调整来构建堆

步骤

  1. 增加堆的长度,在最末尾的地方加入最新插入的元素
  2. 比较当前元素和它的父结点值,如果比父结点值大,则交换两个元素,否则返回
  3. 重复2

时间复杂度

O(N * logN)

示例

  1. 给定⽆序序列,通过 HeapInsert 建⽴⼤根堆。

  2. 插⼊节点[6],与⽗节点[3]进⾏⽐较,并交换。

  3. 插⼊节点[8],与⽗节点[6]进⾏⽐较,并交换。

  4. 插⼊节点[5],与⽗节点[3]进⾏⽐较,并交换。

  5. 插⼊节点[9],与⽗节点[5]进⾏⽐较,并交换。

  6. 节点[9]继续与⽗节点[8]进⾏⽐较,并交换。

  7. 所有节点插⼊,建堆完成。

Heapify 下沉

从最后一个非叶子结点一直到根结点进行堆化的调整。
以大根堆为例,如果当前结点小于某个自己的孩子结点,那么当前结点和这个孩子交换,并持续往下递归调整

时间复杂度

O(N)

第一个非叶子结点

如果根结点在数组中的索引为0,那么最后 一个非叶子结点计算公式lastNonLeaf = (arr.length - 2)/2
设最后一个非叶子结点的位置为x,则最后一个叶子结点一定是2x + 12x + 2

示例

  1. 给定⽆序序列,通过 Heapify 建⽴⼤根堆。
  2. 从最后⼀个⾮叶⼦节点[6]开始调整(arr.length/2-1),与其孩⼦节点中的较⼤节点⽐较,并交换。
  3. 调整节点[5],与其孩⼦节点中的较⼤节点⽐较,并交换。
  4. 继续调整节点[5],与其新孩⼦节点中的较⼤节点⽐较,并交换。
  5. 所有⾮叶⼦节点调整完成,建堆完成。

代码

测试用例

int arr[] = {3,6,8,5,9};

原代码


/*** @Classname HeapSort* @Description 堆排序* 时间复杂度 O(N * logN)*/
public class HeapSort {public static void main(String[] args) {// 测试数据int arr[] = {3,6,8,5,9};//测试maxHeapSort(arr,arr.length);}/*** 堆排序* @param arr* @param len*/public static void maxHeapSort(int[] arr,int len){System.out.println("初始数据:"+Arrays.toString(arr));// 最后一个非叶子结点(len-2)/2  最后一个结点:len-1for(int i = len/2 - 1; i>=0; i--){System.out.println("父结点下标:"+i);maxHeapify(arr,i,len - 1);}// 建堆完毕后结果输出System.out.println("建堆完毕后结果:"+Arrays.toString(arr)+"\n");// 先将第一个元素和已排好的元素前一位做交换(将最大的元素放到后面,类似于直接插入排序),再重新调整,直到排序完毕for (int i = len -1;i>0;i--){System.out.println("本次排序范围:0~"+(i-1));swap(arr,0,i);maxHeapify(arr,0,i-1);}System.out.println("最终结果:"+Arrays.toString(arr));}/*** 建堆* @param arr* @param start* @param end*/public static void maxHeapify(int arr[],int start,int end){// 父结点和子结点下标int dad = start;int son = dad * 2 +1;while(son <= end){ // 子结点在范围内if (son + 1 <= end && arr[son] < arr[son +1]){son++;}if (arr[dad]>arr[son]){ // 父结点大于子节点 跳出函数return;} else { // 否则交换父结点,并继续子结点和孙结点比较swap(arr,dad,son);dad = son;son = dad * 2 +1;}System.out.println("本次交换结果:"+Arrays.toString(arr));}}/*** 交换函数* @param arr* @param i* @param j*/public static void swap(int[] arr,int i ,int j){int temp = arr[j];arr[j] = arr[i];arr[i] = temp;}}

运行结果

步骤

将堆顶结点与末尾结点交换,使末尾结点最大。然后继续调整堆,再将堆顶结点与末尾结点交换,得到第二大结点。如此反复进行交换 重建

  1. 已有⼤根堆,对其进⾏堆排序。
  2. 将堆顶节点[9]与末尾节点[5]进⾏交换,交换完成后将节点[9]移出⼆叉树,并对节点[5]进⾏Heapify调
    整。
  3. 将堆顶节点[8]与末尾节点[3]进⾏交换,交换完成后将节点[8]移出⼆叉树,并对节点[3]进⾏Heapify调

  4. 将堆顶节点[6]与末尾节点[5]进⾏交换,交换完成后将节点[6]移出⼆叉树,并对节点[5]进⾏Heapify调
    整。
  5. 将堆顶节点[5]与末尾节点[3]进⾏交换,交换完成后将节点[5]移出⼆叉树,此时只剩⼀个节点,堆排序
    结束。

【算法】排序_堆排序相关推荐

  1. java 小根堆 排序_堆排序(java实现)

    堆排序就是用大根堆或者小根堆的节点都比左孩子 右孩子大(小)的特性  来构建有序序列. 名词解释: 大根堆:所有节点(n)都比他的左孩子(2n+1)与右孩子(2n+2)大的完全二叉树. 小根堆:所有节 ...

  2. java 快速排序算法简单_排序算法java版,速度排行:冒泡排序、简单选择排序、直接插入排序、折半插入排序、希尔排序、堆排序、归并排序、快速排序......

    先推荐一篇关于排序算法的文章:http://www.cppblog.com/guogangj/archive/2009/11/13/100876.html 本文思路部分来源于上篇文章,但测得的结果似乎 ...

  3. 使用qsort对不连续的内存数据排序_一点就懂的十大经典排序算法

    我是CSDN博主「雨夜※繁华」,这是我的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:一点就懂的经典十大排序算法_大数据_LH is programmin ...

  4. 高效排序算法——希尔排序、堆排序、归并排序、快速排序

    如标题,这里讨论的是基于比较的排序算法中最高效的三种算法和希尔排序.堆排序.归并排序.快速排序的平均时间复杂度均为O(NlogN).前面有介绍过O(N2)的三种简单排序算法(见三大简单排序算法--插入 ...

  5. 排序算法java版,速度排行:冒泡排序、简单选择排序、直接插入排序、折半插入排序、希尔排序、堆排序、归并排序、快速排序...

    先推荐一篇关于排序算法的文章:http://www.cppblog.com/guogangj/archive/2009/11/13/100876.html 本文思路部分来源于上篇文章,但测得的结果似乎 ...

  6. 堆排序时间复杂度_堆排序算法

    堆排序是指利用堆积树这种数据结构所设计的一种排序算法,它是选择排序的一种.可以利用数组的特点快速定位指定索引的元素.堆是一个优先级队列,对于大顶堆而言,堆顶元素的权值最大.将待排序的数组建堆,然后不断 ...

  7. java排序算法总结_排序算法总结及Java实现

    1. 整体介绍 分类 排序大的分类可以分为两种,内排序和外排序.在排序过程中,全部记录存放在内存,则称为内排序,如果排序过程中需要使用外存,则称为外排序.主要需要理解的都是内排序算法: 内排序可以分为 ...

  8. java冒泡排序_JAVA实现经典排序算法(冒泡排序、选择排序、插入排序、希尔排序、堆排序、归并排序、快速排序)...

    冒泡排序 依次比较相邻的元素,若发现逆顺序,则交换.小的向前换,大的向后换,本次循环完毕之后再次从头开始扫描,直到某次扫描中没有元素交换,说明每个元素都不比它后面的元素大,至此排序完成. import ...

  9. 数据结构与算法 / 排序算法 / 堆排序

    一.定义 借助堆结构实现的排序算法被称为堆排序. 二.过程说明 1.建堆 (1)方法1 原地建堆,对于数组来说,从前往后:对于树来说,从下向上. 将数组的第一个元素作为堆顶,第二个元素做向堆中插入数据 ...

  10. 使用qsort对不连续的内存数据排序_常见的内排序和外排序算法

    常见的内排序算法 所谓的内排序是指所有的数据已经读入内存,在内存中进行排序的算法.排序过程中不需要对磁盘进行读写.同时,内排序也一般假定所有用到的辅助空间也可以直接存在于内存中.与之对应地,另一类排序 ...

最新文章

  1. 参加完Python培训后有哪些就业方向
  2. Slackware硬盘安装方法
  3. 基于脑电图的情绪识别BCI应用于DOC患者
  4. hive python udf_python udf方法
  5. 模拟浏览器自动化测试工具Selenium之五Centos系统命令行下部署selenium环境试验
  6. ObjectInputStream和ObejctOutputStream
  7. python求线段长度_python微元法计算函数曲线长度的方法
  8. 1.10 编程基础之简单排序 06 整数奇偶排序 python
  9. 成为大数据顶尖程序员,先过了这些Hadoop面试题!(附答案解析)
  10. 仿新浪微博实现ListBox下拉刷新和到底部自动加载
  11. 2018华为软件精英挑战赛个人总结
  12. 基因家族进化分析之DNA序列批量获取
  13. 【STM32】中断和中断优先级理解
  14. 实验一.MATLAB求解优化问题
  15. 【知识图谱】Neo4j的基本使用及思知1.4亿三元组数据构建知识图谱
  16. PHP简易开发的问卷调查系统
  17. 【经验分享】记录自己使用markdown开始写Blog
  18. 25个有用的 JavaScript 单行代码
  19. 利用XP ie浏览器的漏洞获取shell
  20. 面对金九银十你真的准备好了吗?

热门文章

  1. (转)互联网投顾平台的监管风险:和讯信息
  2. 开放、创新、合作,共赢多样性计算新时代
  3. 【数据预测】基于matlab双向长短时记忆(BiLSTM)数据预测【含Matlab源码 1824期】
  4. 毕设题目:Matlab优化充电
  5. 【优化算法】乌燕鸥优化算法(STOA)【含Matlab源码 1431期】
  6. 用python设计图案_用 Python 打造属于自己的GUI图形化界面
  7. 若泽数据 巨人_面部识别巨人拒绝分享有关其算法数据集的详细信息
  8. keras pytorch_使用PyTorch重新创建Keras功能API
  9. 使用Pytorch的LSTM文本分类
  10. aba问题实际中有什么影响_实际影响是什么?