堆排序详细说明及实现-python

news2024/11/20 0:43:31

先了解什么是堆:

堆的定义

   n个元素的序列 [ k1k2...kn ],满足以下的性质时称之为堆:

        ki≥k2i  且  ki≥k2i+1 (1≤i\left \lfloor n/2\right \rfloor)

    

        ki≤k2i  且  ki≤k2i+1 (1≤i≤ \left \lfloor n/2\right \rfloor)

      如果采用顺序方式即用一维数组存储这个序列,就可以将这个序列的每一个元素ki看成是一棵有n个结点的完全二叉树的第i个结点,其中k1是该二叉树的根结点。


把堆对应的一维数组(即该序列的顺序存储结构)看作一棵完全二叉树的顺序存储,那么堆的特征可解释为:

    1、完全二叉树中任一分支结点的值都小于等于或大于等于它的左、右孩子结点的值。

    2、堆的元素序列中的第一个元素k1,即对应的完全二叉树根结点的值是所有元素中值最小或最大的。

   这种堆分别称小顶(根)堆或大顶(根)堆

        从图中可以看出,在一个堆中,根结点(称堆顶)具有最大值或最小值,而且堆中任何一个非叶子结点的左子树和右子树也是一个堆,根结点到任何一叶子结点的每条路径上的结点的值都是递减或递增的,即堆具有部分有序性。我们以大顶堆为例来讨论堆排序过程。小顶堆类似。

实现思路:

        1、将初始序列建成堆,得到堆顶元素,最大元素

        2、取出堆顶,将堆顶与堆的最后一个元素交换,堆最后一个元素更新

        3、将剩余元素调整为堆,得到新的堆顶为第二大元素

        4、重复步骤2,3知道最后堆为空,此时原序列有序


实现堆排序需解决两个问题:

        (1) 怎样将待排序列构成一个初始堆;

        (2) 输出堆顶元素后,怎样调整剩余的n-1个元素,使其重新成为一个新的堆。

        完成这两项工作,要调用筛选算法。

筛选就是将以结点i为根结点的子树调整为一个堆。

筛选的条件:结点i的左右子树必须已经是堆。

筛选算法的基本思想:

       首先将与堆相应的完全二叉树根结点中的记录移出,该记录称为待调整记录。此时根结点相当于空结点。从空结点的左、右子中选出一个关键字较大的记录,如果该记录的关键字大于待调整记录的关键字,则将该记录上移至空结点中。此时,原来那个关键字较大的子结点相当于空结点。重复上述移动过程,直到空结点左、右孩子的关键字均小于待调整记录的关键字。此时,将待调整记录放入空结点即可。

如图:

        以结点 15 为根节点的子树,左右孩子均已是堆,将根节点用tmp保存记录,15 与左右孩子中较大者比较,即与 54 比较,15小,把 54 置于堆顶位置,此时原 54 位置为空。

        然后看原 54 位置是否有孩子结点,若有孩子结点,让 tmp 与 孩子最大值比较,小于孩子最大值 50 ,那么把 50 放置到空位置,此时原50 位置为空。

        看原 50位置是否有孩子,发现没有孩子,把tmp值放到空位置,调整结束。

 要进行整个序列的堆排序:需要我们将当前堆顶与堆尾记录交换,然后调用筛选算法重新调整,如此反复直至排序结束即可。

 下面以序列 [ 21,25,49,25*,16,9] 为例进行展示:


 代码实现:

def sift(li, low, high):   # 调整为大顶堆
    '''
    :param li:列表
    :param low: 堆的根节点位置
    :param high: 堆的最后一个元素的位置
    :return:
    '''
    i = low  # i最开始指向根节点
    j = 2 * i + 1  # j开始是左孩子
    tmp = li[low]  # 把堆顶存起来
    while j <= high:  # 只要j位置有数,表示有孩子结点
        if j + 1 <= high and li[j + 1] > li[j]:  # 如果有右孩子并且右孩子大于左孩子
            j = j + 1  # j指向右孩子
        if li[j] > tmp:  # 孩子中较大的那个大于堆顶
            li[i] = li[j]  # 把大孩子置于根节点处
            i = j  # 往下看一层,让大孩子为根向下看有无孩子结点,没有就把tmp放到li[i]处
            j = 2 * i + 1  # 此时li[i]已经放到其堆顶了,li[i]可理解为空,若无孩子,把tmp放置此处,完成交换
        else:  # tmp更大,把tmp放到i的位置上
            li[i] = tmp  # 把tmp放到当前某一级堆顶位置上
            break
    else:
        li[i] = tmp  # 把tmp放到大孩叶子节点上


def HeapSort(li):
    n = len(li)
    for i in range((n - 2) // 2, -1, -1):  # 从下向上建堆
        # i 表示建堆的时候调整的部分的根的下标
        sift(li, i, n - 1)  # 下->上调整
    # 建堆完成了, 建造的是大顶堆
    for i in range(n - 1, -1, -1):  # 从列表最后一个元素开始向前与堆顶交换
        # i 指向当前堆的最后一个元素
        li[0], li[i] = li[i], li[0]  # 将堆顶依次换到末尾,每次末尾减一,最后为升序排列
        sift(li, 0, i - 1)  # i-1是新的high,进行调整


li = [49,25,21,25,16,9]
HeapSort(li)
print(li)  # [9, 16, 21, 25, 25, 49]

排序过程如图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/156934.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《回眸2022·圆满收官||展望2023·砥砺奋发》

系列文章目录 文章目录系列文章目录寄言和CSDN相遇大学生活从小白到千粉博主回眸2022|圆满收官展望2023|砥砺奋发致每一个追梦人寄言 岁月不距&#xff0c;时节如流&#xff01;站在岁末的门槛前&#xff0c;回望2022这一年&#xff0c;不知你是否已经完美的书写完2022的答卷&…

计算机工作过程(超详细)

文章目录一、计算机组成框图二、思维导图三、部件剖析&#xff08;1&#xff09;存储器&#xff08;2&#xff09;运算器&#xff08;3&#xff09;控制器四、案例剖析&#xff08;重点&#xff09;&#xff08;1&#xff09;a2&#xff08;2&#xff09;a*b&#xff08;3&…

vscode配置Markdown snippet 的快捷键

Snippet 是&#xff1f; 不同文件的模板语法/代码片段&#xff0c;可以设置好后在不同类型文件快速插入&#xff0c;提高效率。 例如&#xff1a;可以在Markdown使用快捷键生成自己想要的模板内容&#xff0c;自定义输入时tab的跳转位置 具体设置 官方文档 生成snippet的在…

Apache Spark 机器学习 数据源 2

数据源 数据源作为机器学习的数据输入&#xff0c;以供给Spark进行机器学习&#xff0c;Spark技术框架除了支持Parquet、CSV、JSON以及JDBC这些常用的数据源&#xff0c;还提供一些特殊数据源的支持&#xff0c;例如&#xff0c;图像或者LIBSVM。 Parquet数据源 该数据源是a…

2023什么蓝牙耳机值得入手?值得入手的半入耳蓝牙耳机推荐

毫无疑问&#xff0c;近年来蓝牙耳机的外出使用频率越来越高&#xff0c;这是由于其外出携带的便捷性以及配置越来越高端、先进&#xff0c;而半入耳式蓝牙耳机又凭借更舒适的佩戴体验以及便携性受到用户的喜爱。但&#xff0c;面对形形色色的蓝牙耳机&#xff0c;不同价位、不…

Shell中的 test 命令

Shell中的 test 命令用于检查某个条件是否成立&#xff0c;它可以进行数值、字符和文件三个方面的测试。数值测试参数说明-eq等于则为真-ne不等于则为真-gt大于则为真-ge大于等于则为真-lt小于则为真-le小于等于则为真实例num1100num2100if test $[num1] -eq $[num2]thenecho 两…

完全背包理论基础

目录 一.理论基础 二.遍历顺序问题 2.1 01背包 2.2完全背包 3.相关题型 3.1零钱兑换 3.1.数组总和IV 一.理论基础 题目描述&#xff1a; 有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品都有无限个&…

重置Entity Framework Core的数据迁移

本文主要参考文章重置EntityFramework数据迁移到洁净状态&#xff0c;感谢哈~。可能是版本问题&#xff0c;文中所述操作跟我稍微有所出入&#xff0c;故在此做下记录。注意&#xff0c;本人的IDE是JetbrainsRider&#xff0c;并非Visual Studio&#xff0c;但主要操作是通用的…

Spring事务源码解析

Spring事务源码解析一、基本概念1、ACID属性2、事务的隔离级别3、事务行为4、Spring事务的传播级别5、Spring事务支持方式二、Spring事务的执行源码1、事务AOP2、事务处理拦截器TransactionInterceptor2.1 主要流程2.2 尝试创建事务2.3 清除线程事务信息2.4 事务提交2.5 事务异…

品牌控价、淘宝控价、拼多多控价,如何有效利用平台投诉

低价链接&#xff0c;是品牌渠道管控最重要的工作&#xff0c;同时&#xff0c;也是最难的&#xff0c;尤其是非授权低价链接&#xff0c;不受经销管理制度约束&#xff0c;极可能屡次沟通仍不配合整改&#xff0c;进行平台投诉&#xff0c;也不被平台支持诉求。 确实&#xf…

高级ACL的基础配置命令

ACL概述 ACL是由一系列permit或deny语句组成的、有序规则的列表。 ACL是一个匹配工具&#xff0c;能够对报文进行匹配和区分。 ACL的组成 CL由若干条permit或deny语句组成。每条语句就是该ACL的一条规则&#xff0c;每条语句中的permit或deny就是与这条规则相对应的处理动作。…

各社区文艺团队疫情首秀演出《金龄会》受邀提供全程服务

疫情放开后&#xff0c;各地活动逐渐恢复&#xff0c;受到广州各社区的中老年文艺团队邀约&#xff0c;广东省金龄会于1月9日在金龄会演播厅举办了疫情后的首秀——“健康广东&#xff0c;抗疫成功&#xff0c;再创辉煌”广东中老年文化艺术大赛&#xff0c;由广东省健康金龄公…

MAC(m1)-CentOS8 Docker安装MySQL

1、查看可用的MySQL版本 访问 MySQL 镜像库地址&#xff1a;Docker 查看老版本&#xff1a; 2、拉取MySQL镜像 我们可以拉取官方的最新版本的镜像&#xff1a; docker pull mysql:latest 我的MAC m1安装的mysql是8&#xff0c;准备在虚拟机上安装5.7 没找到哦&#xff0c;呜…

MySQL高级篇第01章(Linux下MySQL的安装与使用)

CentOS环境的准备 虚拟机的克隆 mac地址 主机名 ip地址 UUID 查看是否安装过MySQL 如果是用rpm安装&#xff0c;检查一下RPM PACKAGE rpm -qa | grep -i mysql # -i 忽略大小写检查mysql service服务&#xff1a; systemctl status mysqld.service如果存在mysql-libs的旧…

Vue2.0开发之——Vue组件-生命周期(37)

一 概述 了解生命周期和生命周期函数的概念初步了解组件创建的过程了解beforeCreate和Created生命周期函数的特点了解beforeMount和mounted生命周期函数组件运行阶段的生命周期函数组件销毁阶段的生命周期函数 二 了解生命周期和生命周期函数的概念 2.1 生命周期&生命周期…

李宏毅ML-机器学习任务功略

文章目录机器学习任务功略机器学习框架训练模型通用指南1. training loss is large2. training loss is small2.1 training loss is small and testing loss is large2.2 training loss is small and testing loss is small3. 偏差与复杂度的平衡机器学习任务功略 机器学习框架…

Yolov5训练自己的数据集

一、从官网下载最新的yolov5代码二、新建VOCData文件夹三、VOCData文件夹结构新建Annotations文件夹&#xff0c;存放标签简单的xml文件&#xff0c;应该长这样复杂的xml文件&#xff0c;应该长这个样子新建images文件夹&#xff0c;存放图片数据注意&#xff1a;需要观察自己的…

1.1.2半导体二极管的结构、工作原理、参数、伏安特性;

1.结构 内部实际上是一个PN结&#xff0c;将电极引线和其封装在一起就构成了二极管 拓展&#xff1a;点接触型二极管&#xff0c;面接触型二极管 2.工作原理 3.参数&#xff08;以肖特基二极管SS56为例&#xff09; MAX Forward Voltage(最大导通电压) &#xff0c;因为SS5…

Jvm-hotspot 总结系列-完整版(1)类加载器

一、类加载器子系统的作用&#xff08;1&#xff09;类加载器子系统负责从文件系统或网络中加载class文件&#xff0c;class文件在文件开头有特定的文件标识&#xff08;cafebabe&#xff09;咖啡宝贝。&#xff08;2&#xff09;ClassLoader只负责class文件的加载&#xff0c;…

广告业务系统 之 核心通道 —— “日志中心-s2s监测上报”

文章目录广告业务系统 之 核心通道 —— “日志中心-s2s监测上报”s2s 监测上报s2s 、c2s曝光/互动/Win数据上报监测上报AB 实验平台广告业务系统 之 核心通道 —— “日志中心-s2s监测上报” s2s 监测上报 s2s 监测上报&#xff0c;是 ADX 将广告的曝光、互动[点击/播放/下载…