堆排序的Java实现(用最大堆实现从小到大排序)

来源:互联网 发布:淘宝网书包双肩包女生 编辑:程序博客网 时间:2024/05/18 01:07

堆排序原理和示意图不多说了,网上各种有。总结下其最核心的思想:

(1)自底向上,自右向左遍历建堆。这里的底不是指最后一个节点,而是最后一个非叶子节点。每个非叶子节点与其左儿子与右儿子(假如有的话)相比,如果父节点小,那么将左右儿子中较大的那个与父节点交换,然后递归调整被交换的儿子所在的子树,让其继续满足堆性质。

(2)自顶向下调整,使得整个二叉树和其任意子树都满足堆特性。内容和上面建堆中的递归调整一样。注意调整子树时只用调整被交换的那个,而不用左右子树都递归调整。


堆排序算法算是遍历和递归结合的一种典型了。算法中注意父节点和叶子节点的索引对应,感觉绕脑的话用父节点为0,左儿子1,右儿子2多对照下。


下面上算法,具体注释都写在代码里了:

public class HeapSort {    public static void main(String[] args) {        int[] array = {2,1,10,2,-1,7,4,78,-100};        maxHeapSort(array);        for (int i : array) {            System.out.print(i + " ");        }    }    public static void maxHeapSort(int[] array) {        // 建堆,从最后一个非叶子节点开始,自底向上,自右向左遍历建堆        for (int i = array.length/2 - 1; i >= 0; i--) {            adjustMaxHeap(array, i, array.length -1);        }        // 交换头尾元素并调整堆(最大堆,最大元素在前面,交换后到最后面,形成从小到大排序)        for (int i = array.length - 1; i > 0 ; i--) {            swap(array, 0, i); // 交换元素            adjustMaxHeap(array, 0, i -1);        }    }    public static void adjustMaxHeap(int[] array, int begin, int end) {        int leftIndex = 2 * begin + 1; // 左儿子索引        int rightIndex = 2 * begin + 2; // 右儿子索引        boolean hasLeftChild = leftIndex <= end; // 是否左儿子        boolean hasRightChild = rightIndex <= end; // 是否有右儿子        if (hasLeftChild && hasRightChild) {            // 同时存在左右儿子时,左儿子比右儿子和父节点都要大            if (array[leftIndex] >= array[rightIndex] && array[leftIndex] > array[begin]) {                swap(array, begin, leftIndex); // 左儿子上浮                adjustMaxHeap(array, leftIndex, end); //调整左子树堆            }            // 同时存在左右儿子时,右儿子比左儿子和父节点都要大            else if (array[rightIndex] >= array[leftIndex] && array[rightIndex] > array[begin]) {                swap(array, begin, rightIndex); // 右儿子上浮                adjustMaxHeap(array, rightIndex, end); // 调整右子树堆            }        }        // 只存在左儿子而且大于父节点        else if (hasLeftChild && array[leftIndex] > array[begin]) {            // 左儿子上浮,此时不用递归调整左子树,因为堆是完全二叉树,左右儿子不满时说明这是最后一个父节点            swap(array, begin, leftIndex);        }    }    // 交换函数,原理:a ^ a = 0, a ^ 0 = a    private static void swap(int[] array, int i, int j) {        array[i] = array[i] ^ array[j];        array[j] = array[i] ^ array[j];        array[i] = array[i] ^ array[j];    }}


原创粉丝点击