堆排序(Heap Sort)原理及Java实现

先看看堆(Heap)的概念:

对于集合元素 R = { k1 , k2 , k3 , ... kn };

如果满足

1:Ri    >=   R2i ;其中(2i  <= n)

2: Ri   >=   R2i+1 ; 其中(2i+1  <= n )


或满足

1:Ri    =<   R2i ;其中(2i  <= n)

2: Ri   =<   R2i+1 ; 其中(2i+1  <= n )

称为称为该序列是一个堆(最大堆 或 最小堆)。


堆排序的思想是对堆中的第一个元素和最后一个元素进行交换。则最后一个元素是有序的,前面  n-1  个元素是无序的,此时需要对前面n-1个元素进行一次堆调整(将序列中的最值调整到第一个位置,并且其左右子树是一个堆)。直到所有序列有序。


但是我们如何知道给的元素序列是一个堆呢?

答案是这个堆是在排序函数内部自己构造的,用户给定任何序列,程序内部将其构造为一个堆。


堆构造原理:

我们知道只包含一个元素的序列是一个堆。

对于长度为n的元素序列,从n/2开始以后的元素是没有孩子节点的(2i > n),他们都是叶子节点,所以[n/2 , n/2+1 , ... , n]都是一个堆。因此这些元素的父节点和他们进行一次调整就可以形成一个堆,同理只要对这些节点的父节点进行一次筛选就可以形成堆。直到所有的元素都进行了筛选后整个序列就称为一个堆。


筛选函数的实现:

private static void adjustHeap(int data[], int from, int to) {
        int i = from, j = 2 * (from + 1) - 1, tmp;
        while (i <to) {
            if (j + 1 < to && data[j] < data[j + 1]) {
                j++;
            }
            if (j < to && data[i] < data[j]) {
                tmp = data[i];
                data[i] = data[j];
                data[j] = tmp;
            } else {
                break;
            }
            i = j;
            j = 2 * (i+1) - 1;
        }
    }

在实现细节上需要注意的就是数组下标的映射。


堆构造实现代码:

for (int i = (len) / 2; i >= 0; i--)
            adjustHeap(data, i, len);

排序代码:

public static void heapSort(int data[]) {
        if (data == null || data.length <= 1)
            return;
        int len = data.length;
        for (int i = (len) / 2; i >= 0; i--)
            adjustHeap(data, i, len);
        int tmp, k;
        for (int i = 0; i < len; i++) {
            tmp = data[0];
            k = len - i - 1;
            data[0] = data[k];
            data[k] = tmp;
            adjustHeap(data, 0, k);
        }
    }



堆排序(Heap Sort)原理及Java实现

上一篇:Windows 8.1 Hyper-V安装的虚拟机


下一篇:动态规划——5 输入两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数, 使其和等于 m