数据结构---堆排序

2023-10-26


二叉堆的构建,删除,调整是实现堆排序的基础
之前博客写了二叉堆: 二叉堆

  1. 最大堆的堆顶是整个堆中的最大元素。
  2. 最小堆的堆顶是整个堆中的最小元素。

堆排序步骤:

  1. 把无序数组构建成二叉堆。(需要从小到大排序,则构建成最大堆;需要从大到小排序,则构建成最小堆。)
  2. 循环删除堆顶元素,替换到二叉堆的末尾,调整堆产生新的堆顶。

最后删除的元素依次组成了有序的数列。

第一步:删除一个最大堆的堆顶(并不是完全删除,而是跟末尾的节点交换位置)
第二步:再过自我调整,第2大的元素就会被交换上来,成为最大堆的新堆顶

在这里插入图片描述
先删除堆顶元素(跟末尾的节点交换位置)
在这里插入图片描述
再自我调整(第2大的元素就会被交换上来)
在这里插入图片描述
由于二叉堆的这个特性,每一次删除旧堆顶,调整后的新堆顶都是大小仅次于旧堆顶的节点。那么只要反复删除堆顶,反复调整二叉堆,所得到的集合就会成为一个有序集合:

删堆顶9,8变成新堆顶
在这里插入图片描述
删除节点8,节点7成为新堆顶。
在这里插入图片描述
在这里插入图片描述
。。。。循环往复
在这里插入图片描述
删除3,
在这里插入图片描述

原本的最大二叉堆已经变成了一个从小到大的有序集合。
二叉堆实际存储在数组中,数组中的元素排列如下
在这里插入图片描述

JAVA实现

package mysort.heapSort;

import java.util.Arrays;

//构建最大堆
public class heapSort {

    /**
     * “下沉”调整(删除元素)
     * @param array        待调整的堆
     * @param parentIndex  要“下沉”的父节点
     * @param length       堆的有效大小
     */
    public static void downAdjust(int[]array,int parentIndex,int length){
        // temp 保存父节点值,用于最后的赋值
        int temp = array[parentIndex];
        int childIndex = 2*parentIndex+1;
        while (childIndex<length){
            // 如果有右孩子,且右孩子大于左孩子的值,则定位到右孩子
            //找的是左右孩子里面最大的孩子
            if (childIndex+1<length&&array[childIndex+1]>array[childIndex]){
                childIndex++;
            }
            // 如果父节点大于任何一个孩子的值,则直接跳出
            //说明父节点比子节点大了,就没必要交换了(构建最大堆)
            if(temp>=array[childIndex]){
                break;
            }
            ///无须真正交换,单向赋值即可
            array[parentIndex] = array[childIndex];
            //再向下找,直到childIndex>=length,结束
            parentIndex = childIndex;
            childIndex = 2*childIndex+1;
        }
        //最后再把初始的父节点值赋值过去
        array[parentIndex]=temp;
    }

    /**
     * 构建最大堆
     * @param array 待调整的堆
     */
    public static void buildHeap(int[] array){
        // 从最后一个非叶子节点(array.length-2)/2)开始,依次做“下沉”调整
        for (int i = (array.length-2)/2;i>=0;i--){
            downAdjust(array,i,array.length);
        }
    }


    /**
     * 用最大堆排序(升序)
     * @param array  待调整的堆
     */
    public static void heapSort(int[]array){
        // 1. 把无序数组构建成最大堆
        buildHeap(array);
        System.out.println("构建成功,最大堆是:" + Arrays.toString(array));
        //执行堆排序(把堆顶元素删除,放到末尾)
        for (int i =array.length-1;i>0;i--){
            // 最后1个元素和第1个元素进行交换
            int temp = array[i];
            array[i] = array[0];
            array[0] = temp;
            //再把堆顶元素下沉,调整最大堆
            //这里,注意:i
            //随着i--.之前的最后的几位就保存排序好的数字了,就不动了
            downAdjust(array,0,i);
        }
    }
    public static void main(String[] args) {
        int[] arr = new int[]{1,3,2,6,5,7,8,9,10,0};
        heapSort(arr);
        System.out.println("堆排序之后的结果为: "+Arrays.toString(arr));
    }
}

在这里插入图片描述

最大堆排序(升序排序)

空间复杂度是O(1)
时间复杂度:

  1. 把无序数组构建成二叉堆,这一步的时间复杂度是O(n)。
  2. 循环删除堆顶元素,并将该元素移到集合尾部,调整堆产生新的堆顶。需要进行n-1次循环。每次循环调用一次downAdjust方法,所以第2步的计算规模是 (n-1)×logn ,时间复杂度为O(nlogn)。(二叉堆的节点“下沉”调整(downAdjust 方法)是堆排序算法的基础,时间复杂度是O(log n)。)
  3. 两个步骤是并列关系,所以整体的时间复杂度是O(nlogn)。

和快速排序区别

堆排序和快速排序的平均时间复杂度都是O(nlogn),并且都是不稳定排序。
至于不同点,快速排序的最坏时间复杂度是O(n2),而堆排序的最坏时间复杂度稳定在O(nlogn)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构---堆排序 的相关文章

随机推荐

  • python生成随机字符串包含数字字母_如何在Python中生成带有大写字母和数字的随机字符串?...

    您可以使用random choice list of choices 获取随机字符 然后循环遍历并获取列表 最后加入该列表以获取字符串 这里的选择列表是大写字母和数字 例如 import string import random def g
  • 2021年自然语言处理与信息检索国际会议(ECNLPIR 2021)EI检索

    2021年自然语言处理与信息检索国际会议 ECNLPIR 2021 重要信息 会议网址 www ecnlpir org 会议时间 2021年8月13 15日 召开地点 瑞典斯德哥尔摩 截稿时间 2021年6月30日 录用通知 投稿后2周内
  • 2021-12-01 xorm.io/builder

    xorm io builder go和xorm的轻量级快速sql构建器 一般用来构造查询条件 用法 初始化一个cond cond builder NewCond cond的方法 cond And builder语句 且连接 可连接多个con
  • 3张照片打造专属形象!酷蛙FaceChain解密个人写真开源项目,人人AIGC!

    一 背景说明 各类AI写真软件由于其精准的个人形象 精美的生成效果引爆了朋友圈传播 证件照满足了用户刚需 古装照等风格照满足了用户 美照 的需求 酷蛙FaceChain开源项目团队推出了开源版本 希望结合开源社区开发者的力量 可以让图片应用
  • 操作符详解

    在之前的篇章说过 我们不能自己创建操作符 只能使用c语言所给的操作符 那今天就来看看操作符具体有哪些呢 目录 1 操作符分类 2 算术操作符 3 移位操作符 左移操作符 右移操作符 4 位操作符 5 赋值操作符 6 单目操作符 7 关系操作
  • 强化学习笔记------第一章----强化学习概述(超详细)

    强化学习讨论的问题是一个智能体 agent 怎么在一个复杂不确定的环境 environment 里面去极大化他能获得的奖励 首先 我们可以把强化学习和监督学习做一个对比 例如图片分类 监督学习 supervised learning 指的是
  • 一篇史上最全面的 Vue 代码风格指南,建议收藏

    作者 卡喵妹 https juejin cn post 6987349513836953607 一 命名规范 市面上常用的命名规范 camelCase 小驼峰式命名法 首字母小写 PascalCase 大驼峰式命名法 首字母大写 kebab
  • 【云原生】SpringCloud-Spring Boot Starter使用测试

    目录 Spring Boot Starter是什么 以前传统的做法 使用 Spring Boot Starter 之后 starter 的理念 starter 的实现 创建Spring Boot Starter步骤 在idea新建一个sta
  • Computer【HDU-2196】【在线LCA+树的直径】

    题目链接 include
  • PHP 自学教程之自定义函数及数组

    一 自定义函数 自定义函数就是我们自己定义的函数 在PHP中自定义函数格式如下 function funname arg1 arg2 arg3 TODO return values 下面举一个按值传递函数
  • Python 制作马赛克拼合图像

    Python 制作马赛克拼合图像 文章目录 Python 制作马赛克拼合图像 知识点 效果 环境 原理 RGB 色彩空间 HSV 色彩空间 RGB 与 HSV 色彩空间的转换 马赛克图片拼合 数据准备 导入需要的库 计算图像平均 HSV 值
  • Linux下Mysql

    1 安装查看是否已经安装了MYSQLrpm qa mysqlmysql 4 1 7 4 RHEL4 1点开add remove programe里面的mysql的detail勾上mysql server2 启动来检测mysql是否已经启动s
  • Redis系列--redis持久化

    一 为什么需要持久化 redis本身运行时数据保存在内存中 如果不进行持久化 那么在redis出现非正常原因宕机或者关闭redis的进程或者关闭计算机后数据肯定被会操作系统从内存中清掉 当然 redis本身默认采用了一种持久化方式 即RDB
  • Matlab 2021b安装教程-Matlab分析软件下载方法

    MATLAB是美国MathWorks公司出品的商业数学软件 用于算法开发 数据可视化 数据分析以及数值计算的高级技术计算语言和交互式环境 主要包括MATLAB和Simulink两大部分 下载方法 https docs qq com shee
  • 【数据分析实战】基于python对酒店预订需求进行分析

    文章目录 引言 数据加载以及基本观察 缺失值观察及处理 缺失值观察以及可视化 缺失值处理 用户数据探索 什么时间预定酒店将会更经济实惠 哪个月份的酒店预订是最繁忙的 商家数据探索 按市场细分的不同预定情况是怎样的 什么样的人更容易取消预订
  • CCNA考试题库中英文翻译版及答案11

    26 Two routers named Atlanta and Brevard are connected by their serial interfaces as shown in the exhibit but there is n
  • SpringCloud-微服务架构编码构建

    SpringCloud Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具 例如配置管理 服务发现 断路器 智能路由 微代理 控制总线 分布式系统的协调导致了样板模式 使用Spring Cloud开发人员可以快速
  • 010.CMake函数和宏(下)

    文章目录 函数和宏的根本区别 同名覆盖 总结 函数和宏的根本区别 函数和宏之间的一个根本区别 是函数引入了一个新的变量作用域 而宏没有 在函数内定义或修改的变量对函数外同名的变量没有影响 而宏与其调用者共享相同的变量范围 但是请注意 函数不
  • 我的第一个hbuilder项目,基于h5的五子棋游戏

    这是在老师的引导下完成小游戏 以下是今天学习的内容和知识分享 第一个游戏的操作思想 使用hbuilder软件 打开软件可在其帮助中 hbuilder入门 可以了解相应的软件使用方法 使用 菜鸟教程 网站 可在其中学习h5的相关知识 制作五子
  • 数据结构---堆排序

    堆排序 JAVA实现 和快速排序区别 二叉堆的构建 删除 调整是实现堆排序的基础 之前博客写了二叉堆 二叉堆 最大堆的堆顶是整个堆中的最大元素 最小堆的堆顶是整个堆中的最小元素 堆排序步骤 把无序数组构建成二叉堆 需要从小到大排序 则构建成