二叉树实战(七) - 堆排序的实现

/**
 * 堆排序
 */
public class HeapSort {

    public static void main(String[] args) {
        String[] arr = {"S", "O", "R", "T", "E", "X", "A", "M", "P", "L", "E"};
        HeapSort.sort(arr);
        System.out.println(Arrays.toString(arr));
    }

    /**
     * 实现步骤:
     * 1.构造堆
     * 2.得到堆顶元素,这个值就是最大值
     * 3.交换堆顶元素和数组中的最后一个元素,此时最大元素已经放到了合适的位置
     * 4.对堆进行调整,重新让除了最后一个元素的剩余元素中的最大值放到堆顶。
     * 5.重复2-4步骤,直到堆中只剩下一个元素
     */

    // 对source数组中的数据从小到大排序
    public static void sort(Comparable[] source) {
        // 构建堆
        Comparable[] heap = new Comparable[source.length + 1];
        createHeap(source, heap);
        // 定义一个变量,记录未排序的元素中最大的索引
        int N = heap.length - 1;
        while (N != 1) {
            // 通过循环,交换1索引处的元素和排序的元素中最大的索引处的元素
            exch(heap, 1, N);
            // 排序交换后最大元素所在的索引,让它不要参与堆的下沉调整
            N--;
            // 需要对索引1处的元素进行堆的下沉调整
            sink(heap, 1, N);
        }
        // 把heap中的数据复制到source中
        System.arraycopy(heap, 1, source, 0, source.length);
    }

    // 根据原数组,构造出堆heap
    private static void createHeap(Comparable[] source, Comparable[] heap) {
        // 将source中的元素拷贝的heap中,heap中的元素就生成一个堆(此时无序)
        System.arraycopy(source, 0, heap, 1, source.length);
        // 对堆中的元素进行下沉调整(从长度的一半处,往索引扫描)
        for (int i = (heap.length) / 2; i > 0; i--) {
            sink(heap, i, heap.length - 1);
        }
    }

    // 判断堆中索引i处的元素是否小于索引j处的元素
    private static boolean less(Comparable[] heap, int i, int j) {
        return heap[i].compareTo(heap[j]) < 0;
    }

    // 交换堆中索引i和索引j处的值
    private static void exch(Comparable[] heap, int i, int j) {
        Comparable temp = heap[i];
        heap[i] = heap[j];
        heap[j] = temp;
    }

    // 在heap堆中,对target处的元素做下沉,范围是0-range
    private static void sink(Comparable[] heap, int target, int range) {
        while (2 * target < range) {
            // 获取当前结点的子结点的较大结点
            int max; // 记录较大结点所在的索引
            if (2 * target + 1 <= range) {
                if (less(heap, 2 * target, 2 * target + 1)) {
                    max = 2 * target + 1;
                } else {
                    max = 2 * target;
                }
            } else {
                max = 2 * target;
            }
            if (!less(heap, target, max)) {
                break;
            }
            exch(heap, target, max);
            target = max;
        }
    }

}

 

posted @ 2020-05-04 16:08  灰色飘零  阅读(191)  评论(0)    收藏  举报