排序-选择类排序--堆排序简介
参考:数据结构(严蔚敏)
选择类排序有两个经典算法,一个是之前总结过的直接选择排序,另一个则是今天要讲的堆排序
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
排序-选择类排序--堆排序简介相关推荐
- 排序四| 选择类排序(java实现)
选择类排序 选择排序的基本思想是:每一趟从 n-i+1 (i=1,2,-,n)个元素中选取一个关键字最小的元素作为有序序列中第 i 个元素.本节在介绍简单选择排序的基础上,给出了对其进行改进的算法-- ...
- 排序-交换类排序--快速排序简介
交换类排序有冒泡和快排 冒泡排序相对简单,之前总结过: https://blog.csdn.net/u011109881/article/details/80038573 快速排序 参考: 数据结构( ...
- 数据结构-排序-分配类排序-知识点总结归纳3
分配类排序:核心是分配和收集,利用关键字的优先级进行排序的思想 高位优先排序:比如桥牌,先比较花色在比较面值;比如学号,比较级,院,班,号; 低位优先排序: 链式基数排序 思想:基于"分配& ...
- 数据结构之排序算法Java实现(2)——选择类排序之堆排序算法
这个文章旨在存代码,看了很多网上写推排序的算法,感觉写的过于臃肿,我去努力地理解了思想,自己写的,有什么问题欢迎指正. 首先是升序排序,这个要建小顶堆,Java代码如下: public <T e ...
- 排序算法之交换类排序
交换类排序 交换类排序的思想,顾名思义,就是在每一轮的排序过程,通过不断的交换来使每个元素到达最终的位置.常见的两种交换类排序有冒泡排序和快速排序. 冒泡排序(Bubble sort) 冒泡排序作为最 ...
- C语言数组的五种简单排序,选择法排序,冒泡法排序、交换法排序、插入法排序、折半法排序
文章目录 1.选择法排序 2.冒泡法排序 3.交换法排序 4.插入排序 5.折半法排序 6.五种方法比较 1.选择法排序 选择法排序是指每次选择索要排序的数组中的最小值(这里是由小到大排序,如果是由大 ...
- C语言排序之选择法排序
C语言排序算法-选择法排序 选择法排序 相关例程代码 选择法排序 选择法排序指每次选择所要排序的数组中的最大值(降序)或最小值(升序)的数组元素,将这个数组元素的值与最前面没有进行排序的数组元素的值互 ...
- 【排序综合】直接插入排序,希尔排序,快速排序,堆排序,冒泡排序,简单选择排序的简介,实现和算法复杂度分析
目录 1. 直接插入排序 1.1 直接插入排序简介 1. 什么是直接插入排序 2. 排序思想 1.2 排序实现 1. 排序代码 2. 复杂度分析: 3. 运行结果: 1.3 学习链接 2. 希尔排序( ...
- java堆排序工具包_JAVA 排序工具类
提供了以下排序:冒泡排序 选择排序 插入排序 希尔排序 快速排序 归并排序 桶排序 堆排序 package com.xingej.algorithm.sort;import java.util.Arr ...
最新文章
- Python+OpenCV 图像处理系列(3)—— 画线、矩形、画圆、画椭圆、画多边形
- JDBC—02—JDBC的使用;
- 匿名内部类的简单使用
- 每日两句英语-7/7/2009
- VMware虚拟机中VMnet0上的网桥当前未运行
- new,is和as运算符解析及运行时类型,对象,线程堆栈,托管堆之间的联系
- 微软云计算动态登陆“MSDN论坛好帮手”
- 轻松搭建一个Windows SVN服务器
- (图文)HBASE的知识点以及工作原理的详细解释--架构
- 冒泡排序、选择排序、插入排序
- Python实现常用的数据结构
- python中的namespace
- Asp.Net 之Jquery知识点运用
- 洛必达法则及极限问题总结
- CS269I:Incentives in Computer Science 学习笔记 Lecture 20: Fair Division(公平分配)(本系列完结撒花!)
- 微观、宏观、精准 多视角估算数据库性能(选型、做预算不求人)
- linux串口蜂鸣器报警电路,蜂鸣器报警电路图(简单介绍两种!)
- code runner 运行配置
- 奥鹏 大工21秋《计算机网络技术》在线作业
- 使用ffmpeg解码音频sdl(push)播放
热门文章
- Arrays.asList()知识点
- 软件测试2019:第五次作业
- JustOJ1500: 蛇行矩阵
- penpyxl basic function demo code
- 我TM快疯了,在博客园开博短短2个月,经历博客园数次故障。。。
- DataTable的Merge方法和添加datatable到dataset
- php静态登录界面代码,JSP_JSP登录验证功能的实现,静态的登录界面的设计login.htm - phpStudy...
- PAT乙级(1033 旧键盘打字)
- PAT乙级(1029 旧键盘)
- 恩墨学院丨OBCP墨天轮精品课正式上线啦~