写了一个堆排序


堆是一颗完全二叉树
堆中节点不大于或者不小于其父节点

入堆:
直接放入堆内部数据结构的最后,通过shiftUp操作,
与其父节点进行比较,交换位置

出堆:
内部数据结构的第一个(最大或者最小元素)和最后一个元素交换
位置 移除最后一个元素并返回 然后对第一个元素进行shiftDown操作
与其左右子节点比较,找出子节点中最大或者最小的节点交换位置

heapify
对给定的集合构建成最大堆 通过从后往前遍历(n / 2) -1 个节点, 即所有
非叶子节点,进行shiftDown操作。

for (int i = (n >>> 1) - 1; i >= 0; i --) {
       shiftDown(data[i])
}

将第一个元素(最大)和最后一个元素进行交换 让后对前n-1个元素中的第一个
进行shiftDown操作,依次循环,最后完成堆排序

package cn.school;

import java.util.Arrays;

public class Heap {

    //    "原先18现在22"

    public static void main(String[] args) throws Exception {

        Heap main = new Heap();
        main.heapSort(new Integer[]{234, 14, 12, 34, 299, 111});
        
    }

    public > void heapSort(T[] arr) {
        
        //heapify 将传入的数组变成最大堆 对所有非叶子节点进行shiftDown操作
        //从最后一个节点到第一个非叶子节点
        for (int i = (arr.length >>> 1) - 1; i >= 0; i--) {
            shiftDown(i, arr, arr.length);
        }

//        swap(arr, 0, arr.length - 1);
//        shiftDown(0, arr, arr.length - 1);
//        swap(arr, 0, arr.length - 2);
//        shiftDown(0, arr, arr.length - 2);
//      建成最大堆后,将第一个元素和最后一个元素进行交换 之后再对0 - n-1 元素中
//        的0索引进行shiftDown操作,依次往复,最终排好序
        int lastIndex = arr.length - 1;
        while (lastIndex > 0) {
            swap(arr, 0, lastIndex);
            shiftDown(0, arr, lastIndex);
            lastIndex --;
        }

        System.out.println(Arrays.toString(arr));

    }

    private void swap(Object[] arr, int i, int j) {
        Object tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }


    private > void shiftDown(int i, T[] arr, int size) {
        
        //将左右子节点中最大的和自己进行交换
        while (leftChild(i) < size) {
            int j = leftChild(i);
            if (j + 1 < size && arr[j + 1].compareTo(arr[j]) > 0) {
                j++;
            }

            if (arr[i].compareTo(arr[j]) >= 0) {
                break;
            }

            T tmp = arr[i];
            arr[i] = arr[j];
            arr[j] = tmp;

            i = j;
        }
    }

    private int leftChild(int i) {
        return i * 2 + 1;
    }

    private int rightChild(int i) {
        return i * 2 + 2;
    }


}

你可能感兴趣的:(写了一个堆排序)