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

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) 的空间复杂度。那么不借助额外的空间是不是也可以完成堆排序呢?

你可能感兴趣的:(算法)