堆排序 -- 包含笔者 呕心沥血的分析过程

package basic_class_01;
/**
 * 堆排序
 * 
 *  最差时间分析:O(n*log2n) 
 *  平均时间复杂度 :O(n*log2n) 
 *  稳定度:不稳定
 *  空间复杂度 :O(1) 
 *  
 *
 *  堆排序包括两个阶段,初始化建堆和重建堆。
 *      初始化建堆的时间复杂度为O(n),
 *      排序重建堆的时间复杂度为nlog(n)
 *  所以总的时间复杂度为O(n+nlogn)=O(nlogn)
 *  另外堆排序的比较次数和序列的初始状态有关,但只是在序列初始状态为堆的情况下比较次数显著减少   
 *  在序列有序或逆序的情况下比较次数不会发生明显变化。
 *  
 * @author lenovo
 *
 */
public class Code_03_HeapSort {

    public static void heapSort(int[] arr) {
        if(arr == null || arr.length < 2) {
            return;
        }
        // 构建大根堆
        for(int i = 0; i < arr.length; i++) {
            heapInsert(arr,i);
        }

        int size = arr.length;
        swap(arr, 0, --size);  // 首先需要打乱这个大根堆的结构
        while(size > 0) {

            heapify(arr, 0, size);  // 最大的元素放在了大根堆最后的位置了
            // heapify又重新构建了一个大根堆  

            swap(arr,0, --size);  // 再一次把这个大根堆的结构打乱  每一次打乱的之后  都会进行排序
        }

    }

    // 将数组生成大根堆
    // 这个方法是生成一个大根堆:您需要先了解大根堆的构建与数组之间的转换关系
    public static void heapInsert(int[] arr, int index) {
        while(arr[index] > arr[(index - 1) / 2]) { // 如果当前index上的元素比父节点的元素要大,那么就跟父节点交换位置
            swap(arr, index, (index - 1) / 2);  // 
            index = (index - 1) / 2;  // 当前新插入的元素放到了原先的父节点,继续往上判断
        }
    }

    // 大根堆的排序
    // 需要注意的是每一次在排序的时候  交换了位置  还是得保证整个堆的结构是大根堆 
    // 要不然下一次的比较排序就是错的
    public static void heapify(int[] arr, int index, int size) {
        int left = index * 2 + 1;  // 左节点
        while(left < size) {  // 如果是叶子节点  那么就不要
            // 找到左节点 跟 右节点  较大的那一个
            int largest = left + 1 < size && arr[left + 1] > arr[left] ? left + 1 : left;
            // 左  右  节点的数字   不一定会比  当前节点要大   所以还得继续判断
            largest = arr[largest] > arr[index] ? largest : index;
            if(largest == index) {
                break; // 如果当前节点  在这个小堆里面的左右连个点是最大的,那么就不用继续进行判断;额
            }
            swap(arr, largest,index);  // 交换之后往上的都是  符合大根堆的结构的  只需要往下去比较
            index = largest;  // 当前节点需要往下走
            left = index * 2 + 1;

        }
    }

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

}

猜你喜欢

转载自blog.csdn.net/qq_38200548/article/details/81262948
今日推荐