前期概念:

二叉树 完全二叉树 左序遍历 中序遍历 右序遍历 堆 小根堆 大根堆

堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。

Heapify (A, i)

l← left [i]

r← right [i]

if l ≤ heap-size [A] and A[l] > A[i]

then largest ← l

else largest ← i

if r ≤ heap-size [A] and A[i] > A[largest]

then largest ← r

if largest ≠ i

then exchange A[i] ↔ A[largest]

Heapify (A, largest)

堆的概念

在介绍堆排序之前,首先需要说明一下,堆是个什么玩意儿。

堆是一棵顺序存储的完全二叉树。

其中每个结点的关键字都不大于其孩子结点的关键字,这样的堆称为小根堆。

其中每个结点的关键字都不小于其孩子结点的关键字,这样的堆称为大根堆。

举例来说,对于n个元素的序列{R0, R1, ... , Rn}当且仅当满足下列关系之一时,称之为堆:

(1) Ri <= R2i+1 且 Ri <= R2i+2 (小根堆)

(2) Ri >= R2i+1 且 Ri >= R2i+2 (大根堆)

其中i=1,2,…,n/2向下取整;

要点:

首先,按堆的定义将数组R[0..n]调整为堆(这个过程称为创建初始堆),交换R[0]和R[n];

然后,将R[0..n-1]调整为堆,交换R[0]和R[n-1];

如此反复,直到交换了R[0]和R[1]为止。

以上思想可归纳为两个操作:

(1)根据初始数组去构造初始堆(构建一个完全二叉树,保证所有的父结点都比它的孩子结点数值大)。

(2)每次交换第一个和最后一个元素,输出最后一个元素(最大值),然后把剩下元素重新调整为大根堆。

当输出完最后一个元素后,这个数组已经是按照从小到大的顺序排列了。

先通过详细的实例图来看一下,如何构建初始堆。

—————————————————————————————————————————————————————

//代码

public class HeapSort {

private static int[] sort = new int[] { 1, 0, 10, 20, 3, 5, 6, 4, 9, 8, 12, 17, 34, 11 };

public static void main(String[] args) {

System.out.println("Before sort: " + Arrays.toString(sort));

// 没有子节点的才需要创建最大堆,从最后一个的父节点开始
int startIndex = ((sort.length - 1) - 1) >> 1;
// 从尾端开始创建最大堆,每次都是正确的堆
for (int i = startIndex; i >= 0; i--) {
maxHeapify(sort, sort.length, i);
} // 排序,最大值放在末尾,data虽然是最大堆,在排序后就成了递增的
// 末尾与头交换,交换后调整最大堆
for (int i = sort.length - 1; i > 0; i--) {
int temp = sort[0];
sort[0] = sort[i];
sort[i] = temp;
maxHeapify(sort, i, 0);
} System.out.println("After Heapsort : " + Arrays.toString(sort));

}

/**

  • 创建最大堆

    */

    private static void maxHeapify(int[] data, int heapSize, int index) {

    // 当前点与左右子节点比较

    int left = (index << 1) + 1;

    int right = (index << 1) + 2;

    int largest = index;

    if (left < heapSize && data[index] < data[left]) {

    largest = left;

    }

    if (right < heapSize && data[largest] < data[right]) {

    largest = right;

    }

    // 得到最大值后可能需要交换,如果交换了,其子节点可能就不是最大堆了,需要重新调整

    if (largest != index) {

    int temp = data[index];

    data[index] = data[largest];

    data[largest] = temp;

    maxHeapify(data, heapSize, largest);

    }

    }

}

//// end

备注:

参考链接地址:https://wenku.baidu.com/view/af5705ea856a561252d36f71.html

选择排序(2)——堆排序(heap sort)的更多相关文章

  1. [译]async/await中使用阻塞式代码导致死锁 百万数据排序:优化的选择排序(堆排序)

    [译]async/await中使用阻塞式代码导致死锁 这篇博文主要是讲解在async/await中使用阻塞式代码导致死锁的问题,以及如何避免出现这种死锁.内容主要是从作者Stephen Cleary的 ...

  2. Python入门篇-数据结构堆排序Heap Sort

    Python入门篇-数据结构堆排序Heap Sort 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.堆Heap 堆是一个完全二叉树 每个非叶子结点都要大于或者等于其左右孩子结点 ...

  3. 数据结构 - 堆排序(heap sort) 具体解释 及 代码(C++)

    堆排序(heap sort) 具体解释 及 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 堆排序包括两个步骤: 第一步: 是建立大顶堆(从大到小排 ...

  4. 程序员必知的8大排序(二)-------简单选择排序,堆排序(java实现)

    程序员必知的8大排序(一)-------直接插入排序,希尔排序(java实现) 程序员必知的8大排序(二)-------简单选择排序,堆排序(java实现) 程序员必知的8大排序(三)-------冒 ...

  5. 牛客网Java刷题知识点之插入排序(直接插入排序和希尔排序)、选择排序(直接选择排序和堆排序)、冒泡排序、快速排序、归并排序和基数排序(博主推荐)

    不多说,直接上干货! 插入排序包括直接插入排序.希尔排序. 1.直接插入排序: 如何写成代码: 首先设定插入次数,即循环次数,for(int i=1;i<length;i++),1个数的那次不用 ...

  6. Python八大算法的实现,插入排序、希尔排序、冒泡排序、快速排序、直接选择排序、堆排序、归并排序、基数排序。

    Python八大算法的实现,插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得 ...

  7. 直接选择排序(Straight Selection Sort)

    1.定义 选择排序(Selection Sort)的基本思想是:每一趟从待排序的记录中选出关键字最小的记录,顺序放在已排好序的子文件的最后,直到全部记录排序完毕. 常用的选择排序方法有直接选择排序和堆 ...

  8. 简单选择排序(Simple Selection Sort)的C语言实现

    简单选择排序(Simple Selection Sort)的核心思想是每次选择无序序列最小的数放在有序序列最后 演示实例: C语言实现(编译器Dev-c++5.4.0,源代码后缀.cpp) 原创文章, ...

  9. 八大排序算法之三选择排序—简单选择排序(Simple Selection Sort)

    基本思想: 在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换:然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素 ...

随机推荐

  1. C++算法库学习__std::sort__对 vector进行排序_排序后就可以进行使用std::lower_bound进行二分查找(查找第一个大于等于指定值的迭代器的位置)__std::unique

    std::sort      对vector成员进行排序; std::sort(v.begin(),v.end(),compare);   std::lower_bound 在排序的vector中进行 ...

  2. 04JavaScript程序语句

    JavaScript程序语句 2.6程序控制流程 2.6.1选择结构 if <逻辑表达式> 语句 else 语句 if <逻辑表达式> { 语句组 } else { 语句组} ...

  3. PHP 浏览器端输出中文正常,cmd中文乱码

    cmd 运行php脚本乱码问题如果别的编码根据下面的自己换吧!chcp 65001 就是换成UTF-8chcp 936 可以换回默认的GBKchcp 437 是美国英语

  4. LeetCode15——3Sum

    数组中找三个数和为0的结果集 1 // 解法一:先排序 然后固定一个值 然后用求两个数的和的方式 public static List<List<Integer>> three ...

  5. Linux学习笔记记录(四)

  6. FJoi2017 1月20日模拟赛 恐狼后卫(口糊动规)

    Problem 1 恐狼后卫(wolf.cpp/c/pas) [题目描述] 著名卡牌游戏<石炉传说>中有一张随从牌:恐狼后卫.恐狼后卫的能力是使得相邻随从的攻击力提高. 现在有n张恐狼后卫 ...

  7. Python异常捕捉的一个小问题

    问题: names = ['taotao','songwenjing','liu','li']I = iter(names)while True: try: s = next(I) except Ex ...

  8. 九九乘法表-Java

    public class Test1 { public static void main(String[] args){ for(int i=1;i<=9;i++){ for(int j=1;j ...

  9. 九度oj 题目1078:二叉树遍历

    题目1078:二叉树遍历 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5326 解决:3174 题目描述: 二叉树的前序.中序.后序遍历的定义: 前序遍历:对任一子树,先访问跟,然后遍历 ...

  10. 54. spring boot日志升级篇—logback【从零开始学Spring Boot】

    在<44. Spring Boot日志记录SLF4J>章节中有关相关的介绍,这里我们在深入的了解下logback框架. 为什么要使用logback ? --在开发中不建议使用System. ...