排序算法—堆排序

news2024/9/25 1:16:32

文章目录

  • 堆排序
    • 思路过程
      • 建堆
      • 排序
    • 代码实现

堆排序

时间复杂度:O(N*logN)
稳定性:不稳定(相同元素排序后的相对位置改变)

堆的逻辑结构是一棵完全二叉树;堆的物理结构是一个数组,通过下标表示父子结点的关系

这个数组的元素是按照层序遍历(广度优先)的方式存储的。

以下左图为例,其堆的数组元素为 { 6 ,8,10,12,14,16,18 }

【算法】小白的算法笔记:堆排序 (,,• ₃ •,,) - 知乎

以下parent、child、leftchild、rightchild均为下标值 (这些公式表示的是父子结点的关系)

  • parent = (child - 1) / 2
  • leftchild = parent * 2 + 1
  • rightchild = parent * 2 + 2

堆的两个特性:

1. 结构性: 用数组表示一棵完全二叉树
2. 有序性: 任一结点的关键字是其子树所有节点的最大值(或最小值)。
“最大堆”,也称“大顶堆”(或“大根堆”),简称大堆。特点是:父亲大于等于孩子
“最小堆”,也称“小顶堆”(或“小根堆”),简称小堆。特点是:父亲小于等于孩子

了解到这,考虑一个问题,假设有一个深度为4的小堆,那么深度为2的那一层的每一个数据一定都小于深度为3的那一层的每一个元素吗?

不一定,堆的特性规定,只要每个父亲大于(或小于)自己的孩子即可,不需要大于(或小于)同层父亲的孩子。

思路过程

建堆

向下调整算法

前提:左右子树必须同为大堆或小堆
结果:将对象插入到二叉树中,使得插入后的二叉树满足堆的特性

以小堆为例, 父亲跟它的左右孩子的较小值比较,如果父亲比较小值大,那么交换较小孩子和父亲,父亲的值不变位置变化,然后继续和现在位置的左右孩子的较小值比较,父亲大继续交换,直到叶子节点终止(这是算法终止的第一种情况)。如果在到达叶子节点前,出现父亲比左右孩子较小值还要小的情况,那么不执行交换,终止算法执行(第二种终止情况)。
在这里插入图片描述

以大堆为例, 父亲跟它的左右孩子的较大值比较,如果父亲比较大值小,那么交换较大孩子和父亲,父亲的值不变位置变化,然后继续和现在位置的左右孩子的较大值比较,父亲小继续交换,直到叶子节点终止(这是算法终止的第一种情况)。如果在到达叶子节点前,出现父亲比左右孩子较大值还要大的情况,那么不执行交换,终止算法执行(第二种终止情况)。

如果逻辑上的完全二叉树不满足前提条件(根节点开始),怎么办?

既然对根节点没法使用向下调整算法,我们不妨从树的其他满足前提条件的结点开始使用向下调整算法。

从哪些结点开始使用向下调整算法?从叶子结点?

叶子节点没有左右孩子,那么默认就是一个小堆(或大堆),没必要对它使用向下调整算法。

因此,我们开始使用向下调整算法的结点是倒数第一个非叶子节点,然后将下标减1,就是倒数第二个非叶子节点,以此类推,结果建堆成功。

怎么找到倒数第一个非叶子结点?

堆数组最后一个元素是逻辑完全二叉树的最右边的叶子节点,它的父亲就是倒数第一个非叶子结点。

最右边的叶子节点的在数组中的下标是len - 1(len是数组的元素个数),要找它的父亲,用到父子结点关系公式:parent = (child - 1) / 2

代入得到倒数第一个非叶子节点对应的下标值:(len - 1 - 1) / 2

排序

建堆的过程了解了,假如我要排升序,那么我该建大堆还是小堆?

第一反应就是建小堆,最小数在堆顶,堆的物理结构是数组,当我们把第一个元素(建小堆后第一个元素是序列中的最小元素)拿出来后,之后需要在剩下的数中再去选数,但是剩下的树的结构都乱了,需要重新建堆才能选出下一个数,建堆的时间复杂度为O(N),这样反复建堆可以实现排序的目的,不过堆排序就失去了效率优势。

所以我们排升序需要建大堆,最大数在堆顶,每次取堆顶元素,与末尾元素交换,比如:某个序列建大堆后数组元素顺序为:{ 9,8,6,7,3,2,1,5,4,0 },9是堆顶元素,将堆顶元素取出来与0元素交换,得到{ 0,8,6,7,3,2,1,5,4,9 },9是最大元素,不需要再参与排序,除去9后前 len - 1 个元素可以执行向下调整算法,0的左右子树都是大堆,算法执行完毕后,次大的元素到达堆顶,将次大的元素与倒数第二个元素交换,此时倒数一二个元素已经不需要参与排序,以此类推,便实现了顺序堆排序。

代码实现

void Swap(int* p1, int* p2)
{
    int tmp = *p1;
    *p1 = *p2;
    *p2 = tmp;
}

//每趟向下调整算法
void AdjustDown(int* a, int len, int root)
{
    //一次向下调整算法
    int parent = root;
    //假设左孩子大于右孩子,child存储值较大的孩子的下标
    int child = parent * 2 + 1;
    while (child < len)
    {
        if (child + 1 < len && a[child] < a[child + 1])//语句child + 1 < n用于应对某个父亲只有左孩子的情况
        {
            child++;
        }
        if (a[child] > a[parent])
        {
            Swap(&a[child], &a[parent]);
            parent = child;
            child = parent * 2 + 1;
        }
        else
        {
            break;
        }
    }
}


//堆排序
void HeapSort(int* a, int len)
{
    //实现顺序,建大堆
    for (int i = (len - 1 - 1) / 2; i >= 0; i--)
    {
        AdjustDown(a, len, i);
    }
    //排序
    int j = len - 1;
    while (j > 0)
    {
        Swap(&a[0], &a[j]);
        AdjustDown(a, j, 0);
        --j;
    }

}

我们测试一下:

void TestHeapSort()
{
    int a[] = { 2,4,6,4,1,1,8,4,2,0 };
    int len = sizeof(a) / sizeof(int);
    HeapSort(a, len);
    Print(a, len);
}
int main()
{
    TestHeapSort();
    return 0;
}

在这里插入图片描述


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

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

相关文章

[计算机效率] 时间记录工具:ManicTime

3.24 时间记录工具&#xff1a;ManicTime ManicTime是一款数据收集软件&#xff0c;主要用于记录电脑上各种软件使用所花费的时间以及电脑闲置的时间。用户还可以定制记录某一时间段内的系统活动。 数据收集&#xff1a;ManicTime能够静默运行于后台&#xff0c;自动跟踪并收…

美易全球投资中心:金价暴涨背后,美债越来越没人要了?

金价暴涨背后&#xff1a;天量发行的美债越来越没人要了&#xff1f; 近期&#xff0c;国际金价的大涨几乎吸引了全世界投资者的目光。而在狂热的金市买盘背后&#xff0c;而另一避险资产美国国债&#xff0c;则呈现了完全不同的一幕萧条场景。 一系列疲软的美国国债拍卖表现&…

在线知识库如何从零开始搭建?这篇文章来教你!

引言&#xff1a; 有没有想过把那些零散在脑海中的点点滴滴整理起来&#xff0c;建立一个属于自己的在线知识库&#xff1f;无论是个人学习&#xff0c;团队协作&#xff0c;还是企业管理&#xff0c;一个良好的知识库都能帮我们更高效地存储和分享知识。如果你还在为“怎么建知…

创新营销利器:淘宝扭蛋机小程序开发全解析

在数字化浪潮的推动下&#xff0c;淘宝扭蛋机小程序的开发成为了一种全新的购物体验。它巧妙地将传统扭蛋机的乐趣与移动技术的便捷相结合&#xff0c;为用户带来了前所未有的惊喜与互动。 淘宝扭蛋机小程序的开发&#xff0c;不仅是一次技术的革新&#xff0c;更是一次购物方…

基于Springboot+Vue的Java项目-高校心理教育辅导系统开发实战(附演示视频+源码+LW)

大家好&#xff01;我是程序员一帆&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &am…

【C 数据结构】静态链表

文章目录 【 1. 基本原理 】1.1 静态链表中的节点1.2 备用链表 【 2. 静态链表的创建 】2.1 实例1 - 创建静态链表&#xff0c;指定值2.2 实例2 - 创建静态链表&#xff0c;默认值 【 3. 静态链表 添加元素 】【 4. 静态链表 删除元素 】【 5. 静态链表 查找元素 】【 6. 静态链…

模型预测控制MPC(2)—— 无约束线性MPC

前文&#xff1a;模型预测控制MPC&#xff08;1&#xff09;—— 基础概念参考&#xff1a;模型预测控制&#xff08;2022春&#xff09;本文从偏控制的角度介绍无约束线性MPC方法&#xff0c; x , u , J x,u,J x,u,J 分别代表状态、动作和代价函数 文章目录 1. 问题定义1.1 多…

HCIP课后习题之一

1、路由协议用工作机制上分为那几种&#xff1f;分别是&#xff1f; A&#xff1a;两种。分别是静态路由和动态路由&#xff08;可分为IGP和EGP&#xff09; 2、IGP和EGP协议有哪些&#xff1f; A&#xff1a;IGP: RIP、OSPF、ISIS、EIGRP EGP: BGP 3、路由优先级的用途&…

反爬虫之代理IP封禁-协采云IP池

反爬虫之代理IP封禁-协采云IP池 1、目标网址2、IP封禁4033、协采云IP池 1、目标网址 aHR0cDovL3d3dy5jY2dwLXRpYW5qaW4uZ292LmNuLw 2、IP封禁403 这个网站对IP的要求很高&#xff0c;短时间请求十几次就会遭关进小黑屋。如下图&#xff1a; 明显是网站进行了反爬处理&…

FFmpeg: 自实现ijkplayer播放器--06封装打开和关闭stream

文章目录 流程图stream openstream close流程图 stream open 初始化SDL以允许⾳频输出;初始化帧Frame队列初始化包Packet队列初始化时钟Clock初始化音量创建解复用读取线程read_thread创建视频刷新线程video_refresh_threadint FFPlayer::stream_open(const char

Windows下安装GPU版Pytorch

升级Driver到最新版本 Windows搜索栏中输入设备管理器找到显示适配器一项&#xff0c;点击展开&#xff0c;你将看到你的NVIDIA显卡列在其中右键点击你的NVIDIA显卡&#xff0c;选择更新驱动软件…。在弹出的对话框中&#xff0c;选择自动搜索更新的驱动软件。之后&#xff0c…

Scrapy框架 进阶

Scrapy框架基础Scrapy框架进阶 【五】持久化存储 命令行&#xff1a;json、csv等管道&#xff1a;什么数据类型都可以 【1】命令行简单存储 &#xff08;1&#xff09;语法 Json格式 scrapy crawl 自定义爬虫程序文件名 -o 文件名.jsonCSV格式 scrapy crawl 自定义爬虫程…

二叉树的链式存储——补充

/二叉树的结点&#xff08;链式存储) typedef struct BiTNode{ElemType data; //数据域struct BiTNode*lchild,*rchild //左、右孩子指针 }BiTNode,*BiTree;如下图进行存放&#xff1a; 所以&#xff0c;一个二叉树有n个结点的话&#xff0c;那总共就会有2n个指针域…

怎么做预约小程序_探索我们的全新预约小程序

在繁忙的现代生活中&#xff0c;无论是想预约一次美容护理&#xff0c;还是预定一家心仪的餐厅&#xff0c;亦或是安排一次专业的咨询服务&#xff0c;我们都希望能够在最短的时间内完成这些操作&#xff0c;节省时间和精力。如今&#xff0c;一款全新的预约小程序应运而生&…

鸿蒙语言TypeScript学习第16天:【类】

1、TypeScript 类 TypeScript 是面向对象的 JavaScript。 类描述了所创建的对象共同的属性和方法。 TypeScript 支持面向对象的所有特性&#xff0c;比如 类、接口等。 TypeScript 类定义方式如下&#xff1a; class class_name { // 类作用域 }定义类的关键字为 class&am…

AI天使汇联合150家顶级基金、战投,征集优秀AI创业项目

鉴于AI天使汇主办的2024年3月期优秀项目征集活动效果超出预期&#xff0c;3月活动最后TOP20路演者中已有多家快速拿到了TS。 路演活动质量受到了AI创业公司和基金/战投伙伴的高度评价&#xff0c;现在开始四月期活动报名! 本期征集活动联合的顶级基金和战投数量增加到了150家…

MGRE-OSPF接口网络类型实验

OSPF接口网络类型实验 一&#xff0c;实验拓扑 初始拓扑&#xff1a; 最终拓扑&#xff1a; 二&#xff0c;实验要求及分析 要求&#xff1a; 1&#xff0c;R6为ISP只能配置IP地址&#xff0c;R1-R5的环回为私有网段 2&#xff0c;R1/R4/R5为全连的MGRE结构&#xff0c;R…

儿童护眼台灯怎么选?五款必选的高口碑护眼台灯推荐

儿童台灯&#xff0c;想必大家都不会陌生了&#xff0c;是一种学生频繁使用的小灯具&#xff0c;一般指放在桌面用的有底座的电灯。随着近年来儿童青少年的视力急速下滑&#xff0c;很多家长都会选择给孩子选择一款合适的护眼台灯&#xff0c;以便孩子夜晚学习能有个好的照明环…

Stable Diffusion教程:LoRA模型

LoRA模型是一种微调模型&#xff0c;它不能独立生成图片&#xff0c;常常用作大模型的补充&#xff0c;用来生成某种特定主体或者风格的图片。 下载模型 在模型下载网站&#xff0c;如果模型是LoRA模型&#xff0c;网站会特别标识出来。以 liblib.ai为例&#xff1a; 模型左…

three.js捋文档的记录笔记(六):场景 几何体 材质 物体 相机 渲染器的简单理解

三维场景Scene const scene new THREE.Scene();物体形状&#xff1a;几何体 Geometry //创建一个长方体几何对象Geometry const geometry new THREE.BoxGeometry(100, 100, 100); 物体外观&#xff1a;材质Material //创建一个材质对象Material const material new THREE.M…