欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

堆排序(heapsort)

程序员文章站 2022-06-06 23:40:45
...

堆排序

堆排序是利用堆结构(特殊的完全二叉树)实现排序的算法,时间复杂度是O(nlogn)。堆排序不稳定。

原理

堆排序要构建一颗完全二叉树(存储在数组,详见: 二叉树的数组存储),这颗二叉树就是堆。堆有大堆和小堆两种(结构类似)。这里以大堆为例。
在最大堆中每个节点都比子节点大,根节点最大,每个分枝都是一个堆,叶子节点天然就是堆。
构成一个堆之后。然后取堆首-重新构建堆-再取… 元素按大到小依次取出(原地排序),完成排序。

堆排序(heapsort)


示例代码如下:

public class Heapsort {
    void sort(int[] arr){
        //建堆,叶子节点已经是堆了,所以从非叶子节点开始建堆
        for(int i = arr.length/2-1; i >= 0; i--){
            create(arr, i, arr.length - 1);
        }

        //取出跟节点(最大)与最后一个节点交换,然后修正堆
        int i = arr.length-1;//i指向堆的末尾
        while(i > 0){
            int k = arr[0];
            arr[0] = arr[i];
            arr[i] = k;

            i--;//减小堆的规模,这样修正堆时,新的堆不包括刚取出的根节点。相当于不断取出最大的元素。依次形成序列(升序)

            create(arr, 0, i);
        }
    }
    //构建、维护堆 (大堆)
    //这里只考虑将给定节点调整到堆的合适位置
    void create(int[] arr, int start, int end){
        int node = start*2 + 1;//左子节点下标
        //如果有子节点则进入,没有就说明要操作的节点是叶子节点,直接结束
        while(node <= end){
            //在两个字节点中挑一个最大的,(如果是小堆,就挑最小的)
            if(node+1 <= end && arr[node+1] > arr[node]){
                node++;
            }
            //比较父节点和子节点,如果父节点大,说明堆是好的(不用交换),return。否则交换节点后向下迭代
            if(arr[start] >= arr[node]){
                return;
            }else{
                int k = arr[start];
                arr[start] = arr[node];
                arr[node] = k;

                //重新设置父子节点下标,向下迭代,直到构成堆。
                start = node;
                node = start*2+1;
            }
        }
    }
}
相关标签: 堆排序