参考:数据结构(严蔚敏)
选择类排序有两个经典算法,一个是之前总结过的直接选择排序,另一个则是今天要讲的堆排序

0.什么是堆

对于Java中的一个数组Array,如果对于其中所有的元素其下标index满足:Array[index]>=Array[2index+1] && Array[index]>=Array[2index+2](或者Array[index]<=Array[2index+1] && Array[index]<=Array[2index+2])
满足Array[index]>=Array[2index+1] && Array[index]>=Array[2index+2]的数组称为大顶堆,反之则称为小顶堆。
这样讲可能比较抽象,用树的结构可以有助于理解。对于任意数组,都可以模拟成树形结构:
比如数组{12,36,27,65,40,34,98,81,73,55,49}
可以写成如下形式

使用堆的定义,可以发现该数组满足堆的条件。
我们可以发现堆的定义其实就是对于所有元素,满足:根节点比孩子节点大,叶子节点默认满足条件(此时构成大顶堆)

1.堆排序原理

以数组5,6,4,7,2,1,9,10,3为例,堆排序过程如下:

简单描述就是
1.将数组堆化
2.while(无序size>0){
交换下标为0和当前最后一个元素
无序部分总数-1(有序size+1)
对无序部分重新堆化
}
如何将数组堆化?(对一组元素堆化)
首先,叶子节点可以算作已经满足堆的定义,那么可以从第一个非叶子节点(arr.length-1)/2向前调整,使每个元素满足堆的定义。比如数组1,7,8,2的堆化过程如下:



1继续堆化

对一个元素的堆化过程为:
将它跟max(左孩子,右孩子)比较,如果比子节点较大者大,那么已经满足堆的定义,循环结束,否则,跟较大者交换,继续跟max(左孩子,右孩子)比……直到没有孩子节点终止。
如何对无序部分重新堆化?(对一个元素堆化)
已经堆化过的数据,交换下标为0和当前最后一个元素,无序部分只有第零个元素不一定满足堆的定义,问题演化成:

如何重新构建堆的问题。这个其实就是上面的一组元素堆化的拆分,现在只是一个元素。

因此,堆排序的基本操作是对一个元素进行堆化。

2.堆排序Java实现

public class heapSort {public static void main(String[] args) {long arr[] = {5,6,4,7,2,1,9,10,3};// 数组index从0开始// (arr.length-1)/2表示第一个非叶子节点for (int i = (arr.length - 1) / 2; i >= 0; i--) {// 构建大顶堆fixHeapTop(arr, i, arr.length - 1);}long tem = 0;for (int index = arr.length - 1; index > 0;) {//每趟堆排序,无序数-1,有序数+1//swaptem = arr[index];arr[index] = arr[0];arr[0] = tem;fixHeapTop(arr, 0, --index);}for (int i = 0; i < arr.length; i++) {System.out.print(arr[i]+",");}}// 检查index为startIndex的数据与孩子是否满足大顶堆,如果不满足,调整public static void fixHeapTop(long a[], int startIndex, int endIndex) {long temp;int leftChildIndex;//startIndex * 2 + 1表示下标为startIndex的左孩子节点indexfor (leftChildIndex = startIndex * 2 + 1; leftChildIndex <= endIndex; leftChildIndex = leftChildIndex * 2 + 1) {if (leftChildIndex < endIndex && a[leftChildIndex] < a[leftChildIndex + 1]) {leftChildIndex++;//此时代表右孩子index}// compareif (a[startIndex] > a[leftChildIndex]) {//如果当前比较值比孩子中较大的还大,满足大顶堆,循环结束break;}//swaptemp = a[startIndex];a[startIndex] = a[leftChildIndex];a[leftChildIndex] = temp;startIndex = leftChildIndex;}}
}

3.堆排序时间复杂度

堆排序主要分为两部分(其他部分省略,如交换,size-1等等)
1.对数组进行堆化
对长度为n的数组进行堆化从(arr.length - 1) / 2遍历到0,经历了(n-1)/2次
对一个元素进行堆化的时间复杂度和深度有关,比较次数最多为2(h-1),根据之前二叉树的学习可知深度k=log2n向下取整log2n向下取整log_2n向下取整,因此对数组进行堆化的时间复杂度<(n-1)log2n向下取整log2n向下取整log_2n向下取整(因为比较次数最多为2(h-1)中,不是每次n都是最大值,n会递减直到1)
2.对无序部分堆化
进行了n-1趟堆排序,每趟堆排序又是对一个元素进行堆化,因此,时间复杂度和上面类似,都是nlognnlognnlogn级别,两个操作,时间复杂度相加,最终堆排序时间复杂度nlognnlognnlogn

排序-选择类排序--堆排序简介相关推荐

  1. 排序四| 选择类排序(java实现)

    选择类排序 选择排序的基本思想是:每一趟从 n-i+1 (i=1,2,-,n)个元素中选取一个关键字最小的元素作为有序序列中第 i 个元素.本节在介绍简单选择排序的基础上,给出了对其进行改进的算法-- ...

  2. 排序-交换类排序--快速排序简介

    交换类排序有冒泡和快排 冒泡排序相对简单,之前总结过: https://blog.csdn.net/u011109881/article/details/80038573 快速排序 参考: 数据结构( ...

  3. 数据结构-排序-分配类排序-知识点总结归纳3

    分配类排序:核心是分配和收集,利用关键字的优先级进行排序的思想 高位优先排序:比如桥牌,先比较花色在比较面值;比如学号,比较级,院,班,号; 低位优先排序: 链式基数排序 思想:基于"分配& ...

  4. 数据结构之排序算法Java实现(2)——选择类排序之堆排序算法

    这个文章旨在存代码,看了很多网上写推排序的算法,感觉写的过于臃肿,我去努力地理解了思想,自己写的,有什么问题欢迎指正. 首先是升序排序,这个要建小顶堆,Java代码如下: public <T e ...

  5. 排序算法之交换类排序

    交换类排序 交换类排序的思想,顾名思义,就是在每一轮的排序过程,通过不断的交换来使每个元素到达最终的位置.常见的两种交换类排序有冒泡排序和快速排序. 冒泡排序(Bubble sort) 冒泡排序作为最 ...

  6. C语言数组的五种简单排序,选择法排序,冒泡法排序、交换法排序、插入法排序、折半法排序

    文章目录 1.选择法排序 2.冒泡法排序 3.交换法排序 4.插入排序 5.折半法排序 6.五种方法比较 1.选择法排序 选择法排序是指每次选择索要排序的数组中的最小值(这里是由小到大排序,如果是由大 ...

  7. C语言排序之选择法排序

    C语言排序算法-选择法排序 选择法排序 相关例程代码 选择法排序 选择法排序指每次选择所要排序的数组中的最大值(降序)或最小值(升序)的数组元素,将这个数组元素的值与最前面没有进行排序的数组元素的值互 ...

  8. 【排序综合】直接插入排序,希尔排序,快速排序,堆排序,冒泡排序,简单选择排序的简介,实现和算法复杂度分析

    目录 1. 直接插入排序 1.1 直接插入排序简介 1. 什么是直接插入排序 2. 排序思想 1.2 排序实现 1. 排序代码 2. 复杂度分析: 3. 运行结果: 1.3 学习链接 2. 希尔排序( ...

  9. java堆排序工具包_JAVA 排序工具类

    提供了以下排序:冒泡排序 选择排序 插入排序 希尔排序 快速排序 归并排序 桶排序 堆排序 package com.xingej.algorithm.sort;import java.util.Arr ...

最新文章

  1. Python+OpenCV 图像处理系列(3)—— 画线、矩形、画圆、画椭圆、画多边形
  2. JDBC—02—JDBC的使用;
  3. 匿名内部类的简单使用
  4. 每日两句英语-7/7/2009
  5. VMware虚拟机中VMnet0上的网桥当前未运行
  6. new,is和as运算符解析及运行时类型,对象,线程堆栈,托管堆之间的联系
  7. 微软云计算动态登陆“MSDN论坛好帮手”
  8. 轻松搭建一个Windows SVN服务器
  9. (图文)HBASE的知识点以及工作原理的详细解释--架构
  10. 冒泡排序、选择排序、插入排序
  11. Python实现常用的数据结构
  12. python中的namespace
  13. Asp.Net 之Jquery知识点运用
  14. 洛必达法则及极限问题总结
  15. CS269I:Incentives in Computer Science 学习笔记 Lecture 20: Fair Division(公平分配)(本系列完结撒花!)
  16. 微观、宏观、精准 多视角估算数据库性能(选型、做预算不求人)
  17. linux串口蜂鸣器报警电路,蜂鸣器报警电路图(简单介绍两种!)
  18. code runner 运行配置
  19. 奥鹏 大工21秋《计算机网络技术》在线作业
  20. 使用ffmpeg解码音频sdl(push)播放

热门文章

  1. Arrays.asList()知识点
  2. 软件测试2019:第五次作业
  3. JustOJ1500: 蛇行矩阵
  4. penpyxl basic function demo code
  5. 我TM快疯了,在博客园开博短短2个月,经历博客园数次故障。。。
  6. DataTable的Merge方法和添加datatable到dataset
  7. php静态登录界面代码,JSP_JSP登录验证功能的实现,静态的登录界面的设计login.htm - phpStudy...
  8. PAT乙级(1033 旧键盘打字)
  9. PAT乙级(1029 旧键盘)
  10. 恩墨学院丨OBCP墨天轮精品课正式上线啦~