4-5 基础堆排序和Heapify(两个版本的基于堆的排序算法)

来源:互联网 发布:怎么在淘宝论坛发帖子 编辑:程序博客网 时间:2024/05/18 18:44

1、第 1 个版本的基于堆排序的排序算法

思路:借助最大堆这个数据结构,依次往里面放元素,然后再依次倒序取出。

性能比较:100 万个元素。

合并排序,快速排序,3路快速排序,堆排序1

(1)随机

(2)近乎有序

(3)含有大量相同元素的数组

堆排序的时间复杂度是 O(nlogn)。

代码实现:

/** * 第 1 个版本的堆排序算法 * Created by liwei on 17/5/15. */public class HeapSort1 implements ISortAlgorithm {    @Override    public String getName() {        return "第 1 个版本的堆排序算法";    }    @Override    public void sort(int[] arr) {        int length = arr.length;        MaxHeap maxHeap = new MaxHeap(length);        for (int i = 0; i < length; i++) {            maxHeap.insert(arr[i]);        }        for (int i = length - 1; i >= 0; i--) {            arr[i] = maxHeap.extractMax();        }    }}

2、第 2 个版本的基于堆排序的排序算法

理解什么是Heapify?(尝试将一整个数组构建成一个堆的更好的方式,因为此时无须借助额外的空间就完成了最大堆的构建)

关键的部分:

1、所有的叶子节点就是一个最大堆,此时每个堆中的元素只有1个;

2、重要性质:当我们的索引从 1 开始计数的前提下,第 1 个非叶子的节点的索引是 index/2(我们可以使用数学归纳法证明一下),如何让它满足堆的性质呢?shift down 就可以了。

3、从 index/2 递减到根(index=1的时候)依次去完成 shift down,一开始就排除了 length/2 这么多元素。

下面的代码是关键,须要重视!!!

/** * 传递一个数组,形成一个最大堆 * 理解 heapify 是关键 * * @param arr 待排序的数组元素 */public MaxHeap(int[] arr) {    int length = arr.length;    data = new int[length + 1];    for (int i = 0; i < length; i++) {        data[i + 1] = arr[i];    }    // 这一步赋值千万别忘了    count = length;    // 理解这一步是关键 heapify    for (int i = length / 2; i >= 1; i--) {        shiftDown(i);    }}

这样,我们就可以写出我们的第 2 个使用堆排序的算法了,直接把数组传到最大堆这个数据结构里面。

/** * 第 2 个版本的堆排序算法 * Created by liwei on 17/5/15. */public class HeapSort2 implements ISortAlgorithm {    @Override    public String getName() {        return "第 2 个版本的堆排序算法";    }    @Override    public void sort(int[] arr) {        MaxHeap maxHeap = new MaxHeap(arr);        int length = arr.length;        for (int i = length - 1; i >= 0; i--) {            arr[i] = maxHeap.extractMax();        }    }}

重要结论:堆排序在整体上的性能不如归并排序和快速排序。堆这种数据结构更多的时候用于动态数据的维护。

一个数学结论:将 n 个元素逐一插入到一个空堆中,时间复杂度是 O(nlogn)。Heapify 的过程,时间复杂度是 O(n)。

HeapSort2 会快一点的原因是:一上来我们从 n/2 这个地方开始,– 去循环,排除了 n/2 个元素,所以效率肯定比第 1 种好。

可是这两种基于堆的排序算法,我们在堆排序的过程中,使用了额外的空间(MaxHeap 中的数组),使用了 O(n) 的空间复杂度。那么不借助额外的空间是不是也可以完成堆排序呢?

阅读全文
0 0
原创粉丝点击