美文网首页
【排序算法】8.堆排序

【排序算法】8.堆排序

作者: bit_拳倾天下 | 来源:发表于2022-05-23 15:36 被阅读0次

堆排序是利用二叉树顺序存储结构,通过元素交换来完成排序的算法。每次将最大(最小)元素排到 root 位置,然后将 root 和队尾(下一轮则是和倒数第二个元素交换,以此类推)元素进行交换,并在下一轮忽略队尾元素。

冒泡排序时每轮进行一次线性比较,找出最大值(最小值);个人理解,堆排序可以类比成树状冒泡排序。

大顶堆:完全二叉树中,所有父节点大等于左右两节点,兄弟节点之间不做要求。
小顶堆:和大顶堆相反,所有父节点都小于左右两节点。
顺序存储二叉树的特点:

  • 第n个元素的左子结点为第2*n+1个元素(n从0开始,以下同理)
  • 第n个元素的右子结点为第2*n+2个元素
  • 第n个元素的父节点为第(n-1)/2个元素
  • length/2 - 1就是最后一个非叶子节点的索引

思路:

  1. 将树调整成大顶堆或小顶堆。升序排列就用大顶堆,降序就用小顶堆。这时根节点就是最大或最小值。
  2. 将根节点和顺序存储的队尾进行交换。
  3. 然后将剩余的元素重新构建成一个大顶堆,重复 1、2 就可完成排序

java 实现:

/**
 * 堆排序测试
 */
public class HeapSortTest {

    public static void main(String[] args) {
        int[] input = {2,5,4,89,20,89,6,0,54,78,1};
        //1. 第一次构建大顶堆,从最后一个非叶子节点,开始构建子树大顶堆,并依次向上,直到排到根节点
        // length/2 - 1就是最后一个非叶子节点的索引
        for (int i = input.length/2 - 1; i >=0; i--){// @line14
            buildTree(input, i, input.length);
        }
        PrintUtils.print(input);
        //2. 开始交换
        //由于上面已经将数组构建成大顶堆,也就是所有子树都已经是大顶堆,但是由于根节点交换,导致根节点不符合大顶堆
        //所以每次循环从根节点开始构建大顶堆,然后再交换,循环往复
        for (int j = input.length - 1; j > 0; j--){
            int temp = input[0];
            input[0] = input[j];
            input[j] = temp;
            buildTree(input, 0, j);
        }
        PrintUtils.print(input);
    }

    /**
     * 构建大顶堆
     * 此方法,用于将第 i 个元素的子树,构建成大顶堆
     * @param arr 待排序数组
     * @param i 非叶子节点索引
     * @param length 构建大顶堆的节点个数
     */
    public static void buildTree(int[] arr, int i, int length){
        int temp = arr[i];
        //第 i 个节点的左子节点索引为 2*i + 1,右子节点的索引为 2*i + 2
        //每次循环都是找上个节点的左子节点
        for (int k = 2*i + 1; k < length; k = 2*k + 1){
            //比较左右节点
            if (k + 1 < length && arr[k] < arr[k+1]){
                k++;
            }
            if (arr[k] > temp){
                arr[i] = arr[k];
                i = k;
            }else {
                //由 @line14 可知,是从最后一个子树开始构建大顶堆,所以,一旦 arr[k] <= temp,就说明大顶堆构建完成
                break;
            }
        }
        arr[i] = temp;
    }
}

时间复杂度

  • 最优时间复杂度:O(nlog2n)
  • 最坏时间复杂度:O(nlog2n)
  • 稳定性:不稳定

相关文章

  • iOS算法总结-堆排序

    iOS算法总结-堆排序 iOS算法总结-堆排序

  • 堆排序

    转载:图解排序算法(三)之堆排序 预备知识 堆排序 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选...

  • 【排序算法】8.堆排序

    堆排序是利用二叉树顺序存储结构,通过元素交换来完成排序的算法。每次将最大(最小)元素排到 root 位置,然后将 ...

  • 排序算法-堆排序

    参考: Java排序算法(五):堆排序 【算法与数据结构】图说堆排序 【数据结构】排序算法:希尔、归并、快速、堆排...

  • 数据结构与算法

    常见排序算法 堆排序 算法大全 算法大汇总

  • 数据结构

    Q:堆排序 A:1 堆排序算法(图解详细流程)2 堆排序 Q:排序算法时间复杂度与稳定性 选择排序为什么不稳定:举...

  • web开发需要知道的几个算法

    算法分类 快速排序算法 深度优先算法 广度优先算法 堆排序算法 归并排序算法

  • 2018-06-30

    排序算法之堆排序 堆排序是利用堆的数据结构而设计的一种排序算法,堆排序是一种选择排序。可以利用数组的特点快速定位制...

  • 堆排序算法思想

    前两天看了看堆排序算法,啃了半天的书,最后搞明白了堆排序算法,今天有时间给大家说说这个堆排序算法。首先讲一下算法的...

  • 常用排序算法之堆排序

    堆排序算法 运行 输出

网友评论

      本文标题:【排序算法】8.堆排序

      本文链接:https://www.haomeiwen.com/subject/memkprtx.html