Java排序算法 [堆排序]

package cn.com.dom4j.sort;

import java.util.Arrays;

public class Test2 {

    /**
     * 堆排序
     */
    public static > void heapSort(AnyType[] a) {

        // buildHeap
        for (int i = a.length / 2; i >= 0; i--) {
            // 将数组值按初始顺序放入堆中, 从根节点执行下滤操作将构建一个堆
            percolateDown(a, i, a.length);
        }

        // deleteMax
        for (int i = a.length - 1; i > 0; i--) {
            // 在构建了一个 max堆后, 将根节点与最后一个元素互换, 同时将堆的大小 -1, 调整位置, 再次实现堆序
            // 这样每互换一次, 最大的元素就会放在堆的后面 (已经从堆中删除, 不属于堆了), 堆后面的元素会保持顺序, 直到堆中只剩一个元素为止
            swap(a, 0, i);
            percolateDown(a, 0, i);
        }

    }

    /**
     * 下滤操作: 调整某个节点的位置, 以保持堆序
     * @param a 待排序序列
     * @param i 要调整的节点在数组中的索引
     * @param n 堆的大小 (堆中元素个数)
     */
    private static > void percolateDown(AnyType[] a, int i, int n) {

        int child;
        AnyType tmp;

        // tmp记录被调整元素的值, i的值随 child不断改变, 直到比较完所有的子节点 (leftChild(i) < n) 为止
        for (tmp = a[i]; leftChild(i) < n; i = child) {
            child = leftChild(i);
            // child == n - 1时, 其左子节点为堆的最后一个元素, 没有右节点, 无须比较
            // 将该节点与其左右节点比较, 记录其中最小的节点的索引
            if (child != n - 1 && a[child].compareTo(a[child + 1]) < 0) {
                child++;
            }
            // 将需要被调整和节点与其子节点进行比较, 如果小于子节点, 当前节点的值替换为子节点的值 (注意不是交换)
            if (tmp.compareTo(a[child]) < 0) {
                a[i] = a[child];
            } else {
                break;
            }
        }
        // 找到合适的位置后, 直接赋值来避免多余的交换操作
        a[i] = tmp;
    }

    /**
     * 获取某个节点的左子节点在数组中的索引, 因为是从 0开始的, 所以要 +1
     */
    private static int leftChild(int i) {
        return 2 * i + 1;
    }


    /**
     * 交换数组中两个元素的位置
     */
    public static > void swap(AnyType[] arr, int i, int j) {
        if (arr == null || arr.length <= 1 || i == j) {
            return;
        }

        AnyType tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}

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