堆排序 详解+图解

 堆排序是一种基于堆数据结构的排序算法,它的基本思想是将待排序序列构造成一个最大堆,然后将堆顶元素和堆底元素交换,再把堆的大小减一,使堆顶元素下沉到合适的位置,重复以上操作,直到整个序列有序。

堆排序分为两个基本操作:建堆和排序。建堆的过程是把无序序列构建成一个堆,这个过程从最后一个非叶子节点开始,依次将每个节点和其子节点构成一个小堆或大堆。排序的过程是将堆顶元素和堆底元素交换,然后把堆的大小减一,使堆顶元素下沉到合适的位置,重复直到堆的大小变为1为止,最终得到一个从小到大排序的序列。

堆排序的时间复杂度为O(nlogn),空间复杂度为O(1)。它是一种不稳定的排序算法,但由于它的时间复杂度比较稳定,因此在大规模数据排序时表现优秀。

交换排序:堆排序(不稳定的排序)
堆排序是一种树形选择排序,是对直接选择排序的有效改进。

堆是一个完全二叉树,可以分为最大堆和最小堆两种。最大堆的每个父节点都比它的子节点大,而最小堆的每个父节点都比它的子节点小。

堆排序的基本思路是将待排序的元素构造成一个最大堆,此时整个序列的最大值就是堆顶的根节点。将它移走(其实就是将其与堆数组的末尾元素交换位置),然后将剩余的n-1个元素重新构造成一个堆,这样就会得到n个元素中的次小值。如此反复执行,便能得到一个有序的序列了。

堆排序的时间复杂度为O(nlogn),最坏情况下也是O(nlogn),空间复杂度为O(1)。但它的常数因子较大,实际使用时可能不如快速排序和归并排序。

大根堆 87,45,78,32,17,65,53,9 可以看成
                    87
            45                78
        32        17        65        53
    9
    也就相当于是完全二叉树

下面来看一下代码该如何实现

首先是主要思路

void heapsort(int a[], int sz)
{buildmaxheap(a, sz);//初始建堆int i = 0;int temp = 0;for (i = sz-1; i > 1; i--)//n-1趟的交换和建堆过程{temp = a[i];a[i] = a[1];a[1] = temp;headajust(a, 1, i - 1);//把剩余的i-1个元素调整成堆}
}

建大根堆的代码是这样的👇

void buildmaxheap(int a[], int  sz)
{int i = 0;for (i = sz / 2; i > 0; i--)//从i=a[sz/2]~1,反复调整堆headajust(a, i, sz);
}

将元素传入以元素k为根的子树进行调整👇

void headajust(int a[], int k, int sz)
{int i = 0;a[0] = a[k];//暂存子树的根结点for (i = k * 2; i <= sz; i *= 2)//沿较大的子结点向下筛选{if (i < sz && a[i] < a[i + 1])//指向最大的孩子结点i++;if (a[0] >= a[i])break;else{a[k] = a[i];//将a[i]调整到双亲结点上k = i;//修改k的值,以便继续向下筛选}}a[k] = a[0];//被筛选的结点的值放入最终位置
}

完整测试代码

#include<stdio.h>
void headajust(int a[], int k, int sz)
{int i = 0;a[0] = a[k];//暂存子树的根结点for (i = k * 2; i <= sz; i *= 2)//沿较大的子结点向下筛选{if (i < sz && a[i] < a[i + 1])//指向最大的孩子结点i++;if (a[0] >= a[i])break;else{a[k] = a[i];//将a[i]调整到双亲结点上k = i;//修改k的值,以便继续向下筛选}}a[k] = a[0];//被筛选的结点的值放入最终位置
}
void buildmaxheap(int a[], int  sz)
{int i = 0;for (i = sz / 2; i > 0; i--)//从i=a[sz/2]~1,反复调整堆headajust(a, i, sz);
}
void heapsort(int a[], int sz)
{buildmaxheap(a, sz);//初始建堆int i = 0;int temp = 0;for (i = sz-1; i > 1; i--)//n-1趟的交换和建堆过程{temp = a[i];a[i] = a[1];a[1] = temp;headajust(a, 1, i - 1);//把剩余的i-1个元素调整成堆}
}
int main()
{int a[] = { 0,49,38,65,97,76,13,27 };int sz = sizeof(a) / sizeof(a[0]);int j = 0;printf("原始待排序的数组为:");for(j = 1; j < sz; j++)printf("%d ", a[j]);heapsort(a,sz);printf("\n堆排序后的数组为:");for (j = 1; j < sz; j++)printf("%d ", a[j]);return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python的错误和异常处理

一、错误和异常 编程中出现的错误大致可以分为两类&#xff1a;错误和异常。 (一)错误 错误又可以分为两类&#xff1a;语法错误和逻辑错误。 1. 语法错误 语法错误又称解析错误&#xff0c;它是指在编写程序时&#xff0c;程序的语法不符合Python语言的规范&#xff0c;导致…

【Python百练——第2练】使用Python做一个猜数字小游戏

&#x1f490;作者&#xff1a;insist-- &#x1f490;个人主页&#xff1a;insist-- 的个人主页 理想主义的花&#xff0c;最终会盛开在浪漫主义的土壤里&#xff0c;我们的热情永远不会熄灭&#xff0c;在现实平凡中&#xff0c;我们终将上岸&#xff0c;阳光万里 ❤️欢迎点…

Pycharm 搭建 Django 项目,看完这一篇就够了

1. 安装需求 在使用 python 框架 Django 需要注意下面事项 Pycharm 版本是专业版而不是社区版本Pycharm 配置好了 python 解释器 &#xff08;一般我们现在用的都是python3&#xff09;我自己使用的是 Pycharm 版本是2020.1.2 2. 准备工作 2.1 新建项目 首先我们打开 Pycharm …

超融合数据库:解锁全场景数据价值的钥匙

前言 近日&#xff0c;四维纵横对外官宣已完成上亿元 B 轮融资。作为超融合数据库理念的提出者&#xff0c;三年来 YMatrix 持续在超融合数据库领域中保持精进与迭代&#xff0c;对于超融合数据库在行业、场景中的应用和理解也更为深刻。 本篇文章&#xff0c;我们将基于 YMa…

【Linux】常见指令以及具体其使用场景

君兮_的个人主页 即使走的再远&#xff0c;也勿忘启程时的初心 C/C 游戏开发 Hello,米娜桑们&#xff0c;这里是君兮_&#xff0c;随着博主的学习&#xff0c;博主掌握的技能也越来越多&#xff0c;今天又根据最近的学习开设一个新的专栏——Linux&#xff0c;相信Linux操作系…

window11最新版终于可以取消任务栏合并了

windows11一个软件开了多个窗口之后&#xff0c;会自动合并任务栏&#xff0c;很不方便选择其中一个窗口&#xff0c;且没有选项能关闭这一配置 今日发现&#xff0c;最新版完善了这一功能&#xff0c;现在可以关闭自动合并任务栏了 右击任务栏&#xff0c;选择任务栏设置选择…

element表格自定义筛选

文章目录 前言一、简介二、效果展示三、源码总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; …待续 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、简介 修改el-table的筛选…待续 二、效果展示 三、源码 使用方法…

Python爬虫程序中的504错误:原因、常见场景和解决方法

概述 在编写Python爬虫程序时&#xff0c;我们经常会遇到各种错误和异常。其中&#xff0c;504错误是一种常见的网络错误&#xff0c;它表示网关超时。是指客户端与服务器之间的网关通信过程中&#xff0c;服务器在规定的时间内没有返回响应&#xff0c;导致请求超时。此类错误…

【Qt控件之QMessageBox】详解

Qt控件之QMessageBox 描述基于属性的API富文本和文本格式属性严重程度以及图标和Pixmap属性静态函数API 高级用法默认按钮和退出按钮示例使用场景 描述 QMessageBox类提供了一个模态对话框&#xff0c;用于通知用户或向用户提问并接收答案。 消息框显示一个主要文本以提醒用户…

从小白到精通:揭秘perf工具的全部功能与操作技巧

揭秘perf工具的全部功能与操作技巧 一、引言二、理解perf工具的基本概念三、安装与配置perf工具3.1、不同操作系统的perf工具安装3.2、perf工具的配置选项和环境设置 四、perf工具的常用命令和功能4.1、perf工具的基本命令结构和常用参数4.2、perf工具的常见用法和功能4.3、per…

解决恶意IP地址攻击:保卫网络安全的有效方法

随着互联网的发展&#xff0c;网络安全威胁变得日益复杂&#xff0c;其中包括恶意IP地址攻击。这些攻击通常是网络犯罪分子的手段之一&#xff0c;用于入侵系统、窃取数据或进行其他恶意活动。本文将探讨如何解决恶意IP地址攻击&#xff0c;以保护网络安全。 恶意IP地址攻击是…

关于测试组件junit切换testng的示例以及切换方式分享

文章目录 概要首先看看junit和testng的区别实践篇摸拟业务逻辑代码简单对象数据层摸拟类业务逻辑层摸拟类后台任务摸拟类 基于springmockjunit基于springmocktestng 示例的差异点junit与testng的主要变动不大,有以下几个点需要注意注解部分在before,after中testng多出按配置执行…

华为数通方向HCIP-DataCom H12-831题库(多选题:101-120)

第101题 LSR对收到的标签进行保留,且保留方式有多种,那么以下关于LDP标签保留一自由方式的说法 A、保留邻居发送来的所有标签 B、需要更多的内存和标签空间 C、只保留来自下一跳邻居的标签,丢弃所有非下一跳铃邻居发来的标签 D、节省内存和标签空间 E、当IP路由收敛、下一跳…

verilog语言学习

1. 时延 2. 一位全加器设计&#xff1a;三种建模方式 实际的设计中往往是这三种设计模式的混合 3. 4. 5. 6. 7. 建立模型时信号的连接&#xff08;重点&#xff09; 8. initial语句 9. always语句 在always中不能同时判断同一个信号的上升沿&#xff08;posedge&#xff0…

简单明了!网关Gateway路由配置filters实现路径重写及对应正则表达式的解析

问题背景&#xff1a; 前端需要发送一个这样的请求&#xff0c;但出现404 首先解析请求的变化&#xff1a; http://www.51xuecheng.cn/api/checkcode/pic 1.请求先打在nginx&#xff0c;www.51xuecheng.cn/api/checkcode/pic部分匹配到了之后会转发给网关进行处理变成localho…

软件测试之BUG篇(定义,创建,等级,生命周期)

目录 1. BUG 的定义 2. 如何创建 BUG 3. BUG 等级 4. BUG 生命周期 高频面试题&#xff1a; 1. BUG 的定义 当且仅当产品规格书存在且正确时&#xff0c;程序的实现和规格书的要求不匹配时&#xff0c;那就是软件错误。当产品规格说明书没有提到的功能时&#xff0c;以用户…

如何使用drawio画流程图以及导入导出

画一个基本的流程图 你可以在线使用drawio, 或者drawon创建很多不同类型的图表。 如何使用编辑器&#xff0c;让我们以一个最基本的流程图开始。 流程图&#xff0c;就是让你可视化的描述一个过程或者系统。 图形和很少部分的文字表达就可以让读者很快的理解他们需要什么。 创…

如何看待2023年大量劝入C++?

如何看待2023年大量劝入C&#xff1f; 这一段陆陆续续很多人关注这个话题&#xff0c;想提醒大家&#xff0c;c真的很看重领域行业经验&#xff0c;在这里&#xff0c;c只是个工具&#xff0c;相反是这个行业的知识更重要&#xff0c; 最近很多小伙伴找我&#xff0c;说想要一…

制作一个简单的C语言词法分析程序

1.分析组成 C语言的程序中&#xff0c;有很单词多符号和保留字。一些单词符号还有对应的左线性文法。所以我们需要先做出一个单词字符表&#xff0c;给出对应的识别码&#xff0c;然后跟据对应的表格来写出程序 2.程序设计 程序主要有循环判断构成。不需推理即可产生的符号我…

【机器学习可解释性】4.SHAP 值

机器学习可解释性 1.模型洞察的价值2.特征重要性排列3.部分依赖图4.SHAP 值5.SHAP值的高级使用 正文 理解各自特征的预测结果&#xff1f; 介绍 您已经看到(并使用)了从机器学习模型中提取一般解释技术。但是&#xff0c;如果你想要打破模型对单个预测的工作原理? SHAP 值…