0
点赞
收藏
分享

微信扫一扫

排序算法之堆排序


堆排序

有关堆这个数据结构请参考数据结构之堆。

有关批量建堆请参考完全二叉堆之批量建堆。

堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。

堆排序可以认为是对选择排序算法中寻找最小(大)元素的优化。

一般升序采用大顶堆,降序采用小顶堆。

算法思想

  1. 对数组进行原地建堆(heapify)
  2. 重复执行以下操作,直到堆的元素数量为1
  1. 交换堆顶元素与尾元素
  2. 堆的元素数量减1
  3. 对0位置进行1次下滤(siftDown)操作

动图演示

排序算法之堆排序_批量建堆

算法实现

package com.morris.data.struct.sort;

/**
 * 堆排序
 */
public class HeapSort<E extends Comparable> extends AbstractSort<E> {

    private int heapSize;

    @Override
    protected void sort() {

        heapSize = array.length;

        // 先原地构建大顶堆,采用自下而上的下滤
        int lastNotLeafIndex = (heapSize >> 1) - 1; // 最后一个非叶子节点的索引
        for (int i = lastNotLeafIndex; i >= 0; i--) {
            siftDown(i);
        }

        for (int end = heapSize - 1; end > 0; end--) {

            // 最大元素与最后一个元素交换
            swap(0, end);

            heapSize--;

            // 对索引为0的元素进行下滤
            siftDown(0);
        }

    }

    /**
     * 对index的元素进行下滤
     * @param index
     */
    private void siftDown(int index) {
        E v = array[index];

        int childIndex; // index的左子节点

        while ((childIndex = (index << 1) + 1) < heapSize) {

            if(childIndex + 1 < heapSize && cmp(childIndex, childIndex + 1) < 0) {
                // 如果有右子节点,并且右子节点大于左子节点
                childIndex = childIndex + 1;
            }

            if(cmp(v, array[childIndex]) < 0) {
                // 父节点小于最大子节点,用最大子节点覆盖父节点
                array[index] = array[childIndex];
            } else {
                break;
            }

            index = childIndex;
        }

        array[index] = v;
    }
}

堆排序的最好、最坏、平均时间复杂度为O(nlogn),空间复杂度为O(1),是一个不稳定的排序算法。

排序算法之堆排序_java_02


举报

相关推荐

0 条评论