HeapSort

堆排序(不稳定)

  1. 堆排序建堆的时候需要在堆的尾部完成,或者就是删除完成重新排列。
  • 堆排序按照我们的需求能够以最大堆和最小堆的方式进行,一般来说:
  • 排序的方案就是按照堆的定义对树不断进行节点的交换。
//java版本的排序方案
public class HeapSort {
 
    public void HeapAdjust(int[] array, int parent, int length) {//调整堆的函数
        int temp = array[parent]; // temp保存当前父节点
        int child = 2 * parent + 1; // 先获得左孩子
 
        while (child < length) {
            // 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点
            if (child + 1 < length && array[child] < array[child + 1]) {
                child++;
            }
 
            // 如果父结点的值已经大于孩子结点的值,则直接结束
            if (temp >= array[child])
                break;
 
            // 把孩子结点的值赋给父结点
            array[parent] = array[child];
 
            // 选取孩子结点的左孩子结点,继续向下筛选
            parent = child;
            child = 2 * child + 1;
        }
 
        array[parent] = temp;
    }
 
    public void heapSort(int[] list) {
        // 循环建立初始堆
        for (int i = list.length / 2-1; i >= 0; i--) {
            HeapAdjust(list, i, list.length);
        }
 
        // 进行n-1次循环,完成排序
        for (int i = list.length - 1; i > 0; i--) {
            // 最后一个元素和第一元素进行交换
            int temp = list[i];
            list[i] = list[0];
            list[0] = temp;
 
            // 筛选 R[0] 结点,得到i-1个结点的堆
            HeapAdjust(list, 0, i);
            System.out.format("第 %d 趟: \t", list.length - i);
            printPart(list, 0, list.length - 1);
        }
    }
 
    // 打印序列
    public void printPart(int[] list, int begin, int end) {
        for (int i = 0; i < begin; i++) {
            System.out.print("\t");
        }
        for (int i = begin; i <= end; i++) {
            System.out.print(list[i] + "\t");
        }
        System.out.println();
    }
 
    public static void main(String[] args) {
        // 初始化一个序列
        int[] array = {
                1, 3, 4, 5, 2, 6, 9, 7, 8, 0
        };
 
        // 调用快速排序方法
        HeapSort heap = new HeapSort();
        System.out.print("排序前:\t");
        heap.printPart(array, 0, array.length - 1);
        heap.heapSort(array);
        System.out.print("排序后:\t");
        heap.printPart(array, 0, array.length - 1);
    }
}

复杂度情况

排序方法 空间复杂度 稳定性 复杂性
堆排序 O(1) 不稳定 较复杂
时间复杂度 平均 最坏 最好
nlog2n) O(nlog2n) O(nlog2n)

时间复杂度

堆的存储表示是顺序的。因为堆所对应的二叉树为完全二叉树,而完全二叉树通常采用顺序存储方式。

当想得到一个序列中第k个最小的元素之前的部分排序序列,最好采用堆排序。

因为堆排序的时间复杂度是O(n+klog2n),若k≤n/log2n,则可得到的时间复杂度为O(n)

posted @ 2020-10-16 11:30  Marvel_Iron_Man  阅读(73)  评论(0编辑  收藏  举报