排序算法—堆排序

文章目录

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

堆排序

时间复杂度: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;
}

在这里插入图片描述


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

推荐5款 深受欢迎 的AI开源项目

本周 GitHub圈选 项目推荐&#xff1a; InstantID&#xff08;小红书AI图像生成工具&#xff09; CWMP&#xff08;ChatGPT Web Midjourney Proxy&#xff09; aicover&#xff08;AI红包封面制作神器&#xff09; ML-YouTube-Courses&#xff08;机器学习的学习库&#xff…

深入K8S实战

K8S: 深入K8S实战进阶篇 1、搭建 Kubernetes 集群 1.1、搭建方案 1.1.1、minikube minikube 是一个工具&#xff0c; 能让你在本地运行 Kubernetes。 minikube 在你的个人计算机&#xff08;包括 Windows、macOS 和 Linux PC&#xff09;上运行一个一体化&#xff08;all-i…

Gartner 《2024安全和风险管理技术路线图》:高价值技术 DSP 进入广泛部署阶段

近期&#xff0c;Gartner 发布《2024年技术采用路线图&#xff1a;安全与风险管理》&#xff08;以下简称&#xff1a;《路线图》&#xff09;&#xff0c;该信息图表识别了全球企业正在采用的 44 种与安全相关的技术&#xff0c;并根据采用阶段、部署风险和企业价值进行了映射…

HuggingFists-如何复用流程(二)

上一篇文章中&#xff0c;我们介绍了如何在HuggingFists系统中复用流程。如何定义流程,接收外部数据流以及写出数据流。通过接收和写出数据流实现流程的嵌套引用。在实际的应用场景中&#xff0c;被引用的子流程除了需要与主流程的数据流进行交互外&#xff0c;有时其流程内部的…

悬镜安全持续霸榜安全牛《中国网络安全全景图》供应链安全赛道

2024年4月12日&#xff0c;国内知名网络安全专业咨询机构安全牛正式发布了第十一版网络安全行业全景图&#xff08;以下简称“全景图”&#xff09;&#xff0c;悬镜安全凭借沉淀多年的技术创新和应用实践&#xff0c;连续四年强势领跑数字供应链安全领域&#xff0c;引领DevSe…

MyBatis-Spring整合

引入Spring之前需要了解mybatis-spring包中的一些重要类&#xff1b; http://www.mybatis.org/spring/zh/index.html 什么是 MyBatis-Spring&#xff1f; MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。 知识基础 在开始使用 MyBatis-Spring 之前&#x…

Sorting Algorithms in Python (排序算法)

本篇文章主要介绍几种经典排序算法&#xff1a;冒泡排序、快速排序、选择排序、堆排序、插入排序、希尔排序、归并排序、桶排序和基数排序。并给出用python实现的算法代码。 目录 一、冒泡排序 二、快速排序 三、选择排序 四、堆排序 五、插入排序 六、希尔排序 七、归…

大厂Java笔试题之判断一个数是否自守数

题目&#xff1a;自守数是指一个数的平方的尾数等于该数自身的自然数。例如&#xff1a;25^2 625&#xff0c;76^2 5776&#xff0c;9376^2 87909376。 请求出n(包括n)以内的自守数的个数 数据范围&#xff1a; 1≤n≤10000 输入描述&#xff1a; int型整数 输出描述&…

推荐3个yyds的AI开源项目!

在这个数字化飞速发展的时代&#xff0c;有一堆人工智能开源工具&#xff0c;它们正悄悄地改变着我们的生活和工作方式。今天&#xff0c;我就带大家一起来深度了解几款近期大火的人工智能工具&#xff0c;看看它们是怎样为我们的生活带来便利和创新的。 马赛克杀手APISR 首先…

怎样关闭谷歌浏览器自动更新,亲测ok

步骤一 在服务中禁用Google更新 步骤二 Chrome更新是利用Update文件夹里的升级程序来升级的&#xff0c;需要要删除里面的文件&#xff0c;再让Chrome没法在Update文件夹里继续自动生成更新程序。所以还要清空Update文件夹并设置权限&#xff0c;让Chrome没有权限修改这个文件…

分享|为什么说Temu项目是蓝海项目?

在当今日新月异的互联网行业中&#xff0c;Temu项目以其独特的商业模式和前瞻性的市场布局&#xff0c;迅速崛起成为一颗耀眼的新星。它被业内普遍认为是一片尚未被完全开发的蓝海&#xff0c;具有巨大的市场潜力和发展空间。那么&#xff0c;为什么说Temu项目是蓝海项目呢? 首…

爬虫的目的是做什么

通过网站域名获取HTML数据解析数据&#xff0c;获取想要的信息存储爬取的信息如果有必要&#xff0c;移动到另一个网页重复过程 这本书上的代码的网址是 &#xff1a; GitHub - REMitchell/python-scraping: Code samples from the book Web Scraping with Python http://shop.…

Linux sed

文章目录 1. 基本功能2.sed替换ssed配合grep和管道操作符的例子 3.sed中的删除和添加3.1 d删除3.2 a i添加添加多行 4.sed行替换替换包含某字符的行 5.单字符替换 y6. p打印命令打印含有目标字符的行sed中包含多个指令&#xff0c;使用{} 7.sed w 写入文件8.sed r 读取文件9.se…

【数据结构】第三节:单链表

前言 本篇要求掌握的C语言基础知识&#xff1a;指针、结构体 目录 前言 单链表 概念 对比链表和顺序表 创建链表 实现单链表 准备工作 打印链表 创建节点并初始化 尾插 二级指针的调用 尾插代码 头插 尾删 头删 查找&#xff08;返回节点&#xff09; 在指定位…

Blender表面细分的操作

在使用Blender的过程中,刚开始创建的模型,都会比较少面,这样操作起来比较流畅,减少电脑的计算量,当设计快要完成时,就会增加表面细分,这样更加圆滑,看起来更加顺眼。 比如创建一个猴头,它会默认显示如下: 从上图可以看到,有一些表面会比较大,棱角很多。 这时候你…

java:Java类与对象(继承篇)

前言&#xff1a; 为什么要继承&#xff1f; 如&#xff1a;创建两个类&#xff0c;一个猫类&#xff0c;一个狗类&#xff0c;猫与狗都有眼睛&#xff0c;嘴巴&#xff0c;鼻子这些相同的属性&#xff0c;为了避免代码重复我们可以通过创建一个动物类&#xff0c;包含这些重复…

更改android 安装的sdk版本

打开sdk manager 勾选show details 就可以选择了。

CTF之comment

网站的登录框里有提示 账号&#xff1a;zhangwei 密码&#xff1a;zhangwei***&#xff08;后三位要自己猜&#xff09; 用burpsuit抓包爆破发现密码为zhangwei666 进去后就一个留言榜&#xff08;目前没发现怎么用&#xff09; 扫一下网站发现git泄露 1.下载 进入root用户&…

【讲解下常见的分类算法】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

ELK企业级日志分析系统(elasticsearch+logstash+kibana)

目录 一.ELK概述 1.定义 &#xff08;1&#xff09;ElasticSearch &#xff08;2&#xff09;Kiabana &#xff08;3&#xff09;Logstash &#xff08;4&#xff09;Filebeat 2.filebeat结合logstash带来好处 3.为什么要是用ELK&#xff1f; 4.完整日志系统基本特征 …