当前位置: 首页 > news >正文

深入浅出排序算法之堆排序

目录

1. 算法介绍

2. 执行流程⭐⭐⭐⭐⭐✔

3. 代码实现

4. 性能分析


1. 算法介绍

堆是一种数据结构,可以把堆看成一棵完全二叉树,这棵完全二叉树满足:任何一个非叶结点的值都不大于(或不小于)其左右孩子结点的值。若父亲大孩子小,则这样的堆叫作大顶堆;若父亲小孩子大,则这样的堆叫作小顶堆。

根据堆的定义知道,代表堆的这棵完全二叉树的根结点的值是最大(或最小)的,因此将一个无序序列调整为一个堆,就可以找出这个序列的最大(或最小)值,然后将找出的这个值交换到序列的最后(或最前),这样,有序序列关键字增加1个,无序序列中关键字减少1个,对新的无序序列重复这样的操作,就实现了排序。这就是堆排序的思想。

堆排序中最关键的操作是将序列调整为堆。整个排序的过程就是通过不断调整,使得不符合堆定义的完全二叉树变为符合堆定义的完全二叉树。

2. 执行流程⭐⭐⭐⭐⭐✔

建堆是先从自下而上,从右往左建

初始堆的每一个结点都要满足堆的定义,也就是父节点的值大于左右孩子结点的值!!!

选出最大值,是将根结点和最后一个结点互换,然后继续构建大顶堆!!!

⭐⭐⭐堆顶和最后一个元素交换,才算一趟,也是该趟的最终序列结果!!!

建堆和排序结果是两个阶段,但同属于一趟中。

图示如下:

3. 代码实现

为了三个步骤:

步骤一:先建堆(大根堆或者小根堆)

步骤二:交完堆顶和最后一个元素,然后堆的大小减一

步骤三:向下调整堆

步骤一只需实现一次,步骤二和步骤三循环执行,得到最终的有序序列。

    //开始排序:堆排序分为三个功能 ①开始建堆,②交换,③向下调整,重复②和③步public static void heapSort(int[] array,int len){int end = len - 1;//确定最后一个结点的下标createHeap(array);//建堆//当只剩下一个结点的时候,就不需要交换while(end > 0){//交换swap(array,0,end);//向下调整shiftDown(array,0,end);//调整完一个结点,下一个end--;}}//交换数据public static void swap(int[] array,int i,int j){int tmp = array[i];array[i] = array[j];array[j] = tmp;}//堆排序(大根堆)//从上往下建堆,所以先找父节点,再找孩子结点public static void createHeap(int[] array){for(int parent = (array.length - 1 - 1) / 2;parent >= 0;parent--){shiftDown(array,parent,array.length);}}//向下调整public static void shiftDown(int[] array,int parent,int len){//定义一个记录孩子下标的变量(左孩子)int child = 2 * parent + 1;//判断父节点和孩子结点的大小,至少左孩子要存在while(child < len){//比较左右孩子if((child + 1) < len && array[child] < array[child + 1]){child++;}//判断父节点和孩子节点if(array[child] > array[parent]){swap(array,child,parent);parent = child;child = 2 * parent + 1;}else{break;}}}
    public static void main(String[] args) {int[] a = {5,4,3,2,1};Sort.heapSort(a, a.length);for (int x : a) {System.out.print(x + " ");}}

4. 性能分析

时间辅助度空间复杂度
O(N*logN)O(1)
数据不敏感数据不敏感

稳定性:不稳定。

来上解析,怎么计算这个时间复杂度。

(1)步骤一的时间复杂度:首先知道有N个结点开始建堆,这个时间复杂度就是O(N),大家可以去看看这篇文章,里面有讲建堆的时间复杂度。链接如下:

数据结构——堆、堆排序和优先级队列(代码为Java版本)

(2)步骤二和步骤三循环的时间复杂度:那么我第一个结点交换时,需要向下调整为log(N - 1)层;交换第二个结点后,需要向下log(N - 2),接下来就是log(N - 3),log(N - 4),……,log1。所以总的调整次数是log(N - 1) + log(N - 2) + log(N - 3) + log(N - 4) + …… + log1 = log((N - 1)!)。

我们可以在网上看到堆排序的时间复杂度是O(N*logN),这是堆排序的大致估算(我们算时间复杂度都是算个大概),其实log((N - 1)!) 约等于 NlogN。下面是我的证明结果:

① 使用夹逼准则证明:

先求上限:\log \left ( n!\right ) = \sum_{i = 1}^{n}\log \left ( i \right )\leqslant \sum_{i=1}^{n}\log \left ( n \right )=\log n^{n}=O\left (n\log n \right )

再求下限:

因为 n! \geqslant \left ( \frac{n}{2} \right )^{\frac{n}{2}}

所以 \log \left ( n! \right )\geqslant \log \left ( \frac{n}{2} \right )^{\frac{n}{2}}= \frac{n}{2}\log \frac{n}{2}= \frac{n}{2}\log n-\frac{n}{2}\log 2

当 n\geqslant 4 时,\frac{n}{2}\log 2=\frac{1}{4}n\log 4\leqslant \frac{1}{4}n\log n               

② 则有:

\log \left ( n! \right )\geqslant \frac{n}{2}\log n-\frac{n}{2}\log 2\geqslant \frac{n}{2}\log n-\frac{1}{4}n\log n=\frac{1}{4}n\log n\approx \Omega \left ( n\log n \right )     

③结论:\log \left ( n! \right ) 既是 n\log n 的低阶函数,又是 n\log n 的高阶函数,因此是 n\log n 的同阶函数!

(3)由于上面的证明步骤,我们可以知道堆排序的时间复杂度是  O\left ( n\log n \right ) 。

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           

相关文章:

深入浅出排序算法之堆排序

目录 1. 算法介绍 2. 执行流程⭐⭐⭐⭐⭐✔ 3. 代码实现 4. 性能分析 1. 算法介绍 堆是一种数据结构&#xff0c;可以把堆看成一棵完全二叉树&#xff0c;这棵完全二叉树满足&#xff1a;任何一个非叶结点的值都不大于(或不小于)其左右孩子结点的值。若父亲大孩子小&#x…...

Linux 命令(11)—— tcpdump

文章目录 一、命令简介二、使用方法三、命令选项四、基本语法和使用方法1. 显示 ASCII 字符串2. 抓取特定协议的数据3. 抓取特定主机的数据4. 将抓取的数据写入文件5. 行缓冲模式 五、理解tcpdump的输出六、过滤表达式1. Host 过滤2. Network 过滤3. Proto 过滤4. Port 过滤5. …...

8.自定义组件布局和详解Context上下文

pages/index.vue layout布局运行在服务端 1、在项目的目录下新建layout文件夹&#xff0c;并新建一个blog.vue布局文件 2、在页面中的layout函数里&#xff0c;返回刚才新建布局文件的名字blog就可以使用了 export default {...layout (context) {console.log(context)retu…...

几个Web自动化测试框架的比较:Cypress、Selenium和Playwright

介绍&#xff1a;Web自动化测试框架对于确保Web应用程序的质量和可靠性至关重要。它们帮助开发人员和测试人员自动执行重复性任务&#xff0c;跨多个浏览器和平台执行测试&#xff0c;并在开发早期发现问题。 以下仅代表作者观点&#xff1a; 本文探讨来3种流行的Web自动化测…...

Android Studio中配置aliyun maven库

当下载第三方库失败的时候&#xff0c;通过Android Studio中配置aliyun maven库&#xff0c;达到正常下载库效果 在项目的根build.gradle里面&#xff08;不是module&#xff09;buildscriptde对应位置添加配置&#xff1a; maven { url https://maven.aliyun.com/repository/…...

记录使用阿里 ARoute 遇到的坑

1.按照官方一个配置好之后 尝试使用 跳转出现 Aroute Theres no route matched path"" 我这边遇到的坑是配置问题 kotiln 使用了 Java的配置 plugins {id("com.android.application")id("org.jetbrains.kotlin.android")id("kotlin-kapt&…...

lesson2(补充)关于const成员函数

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 前言&#xff1a; 将const 修饰的 “ 成员函数 ” 称之为 const 成员函数 &#xff0c; const 修饰类成员函数&#xff0c;实际修饰该成员函数 隐含的 this 指针 &#xff0c;表明在该成员函数中不能对类的任何成员进行修改…...

前端 :用HTML ,JS写一个 双色球彩票中将机制,因为时间不够,加上本人懒没有用CSS美化界面,多包涵

1.HTML <body><div id"content"><div id "top"><div id "username">用户号码&#xff1a;</div><div id "qiu"><span id "red">红球&#xff1a;</span><input id…...

前端页面如何自适应--4种方法

前端页面有很多方法可以实现。这里我将介绍五种常用的方法&#xff0c;并提供相应的代码示例。 1. 使用CSS媒体查询 通过CSS媒体查询&#xff0c;可以根据不同的屏幕尺寸应用不同的样式。在Vue组件中&#xff0c;可以在样式部分使用媒体查询&#xff0c;使排版根据屏幕大小进…...

2024王道考研计算机组成原理——总线

6.1 总线概述 每一个外设都通过IO接口和DB、CB、AB相连 三系统总线结构&#xff1a; 桥有总线仲裁的功能&#xff0c;就是把某一总线的使用权分给哪个设备&#xff1f; 6.1.2 总线的性能指标 总线复用&#xff1a;分时传输地址&数据 6.2 总线仲裁 通过控制总线来发送使…...

【Linux】进程概念(下)

进程概念 一、环境变量1. 命令行参数2. 常见的环境变量&#xff08;1&#xff09;PATH&#xff08;2&#xff09;PWD&#xff08;3&#xff09;HOME&#xff08;4&#xff09;env 查看所有的环境变量 3. 获取环境变量&#xff08;1&#xff09;通过代码获取环境变量&#xff08…...

基于Spring Boot的本科生就业质量设计与实现

摘 要 信息化爆炸的时代&#xff0c;互联网技术的指数型的增长&#xff0c;信息化程度的不断普及&#xff0c;社会节奏在加快&#xff0c;每天都有大量的信息扑面而来&#xff0c;人们正处于数字信息化世界。数字化的互联网具有便捷性&#xff0c;传递快&#xff0c;效率高&am…...

238. 除自身以外数组的乘积 --力扣 --JAVA

题目 给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请不要使用除法&#xff0c;且在 O(n) 时间复…...

如何判断一个类是线程安全的

线程安全 一个类或者程序提供的接口&#xff0c;多个线程之间的切换不会导致该接口的执行结果存在二义性&#xff0c;也就是不必考虑同步问题。 或者说一段代码可能会被多个线程同时执行&#xff0c;如果每次运行的结果和单线程执行的结果是一样的&#xff0c;并且其他变量的…...

MyBatis的各种查询功能

文章目录 情景查询一个实体类对象查询一个List集合查询单个数据查询一条数据为map集合查询多条数据为map集合方法一方法二 情景 如果查询出的数据只有一条&#xff0c;可以通过 实体类对象接收List集合接收Map集合接收&#xff0c;结果{password123456, sex男, id1, age23, us…...

【Tomcat】如何在idea上部署一个maven项目?

目录 1.创建项目 2.引入依赖 3.创建目录 4.编写代码 5.打包程序 6.部署项目 7.验证程序 什么是Tomcat和Servlet? 以idea2019为例&#xff1a; 1.创建项目 1.1 首先创建maven项目 1.2 项目名称 2.引入依赖 2.1 网址输入mvnrepository.com进入maven中央仓库->地址…...

Three.js 材质的 blending

Three.js 材质的 blending // blending modes export type Blending | typeof NoBlending| typeof NormalBlending| typeof AdditiveBlending| typeof SubtractiveBlending| typeof MultiplyBlending| typeof CustomBlending;// custom blending destination factors export t…...

关于pcl 给new出的数据赋值报错问题

pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>); for (size_t i 0; i < cloud->points.size (); i) //填充数据 { cloud->points[i].x 1024 * rand () / (RAND_MAX 1.0f); cloud->points[i].y 1024…...

window11 更改 vscode 插件目录,释放C盘内存

由于经常使用vscode开发会安装一些代码提示插件&#xff0c;然后C盘内容会逐渐缩小&#xff0c;最终排查定位到vscode。这个吃内存不眨眼的家伙。 建议&#xff1a;不要把插件目录和vscode安装目录放在同一个位置&#xff0c;不然这样vscode更新后&#xff0c;插件也会消失。 v…...

【PyQt学习篇 · ⑥】:QWidget - 事件

文章目录 事件消息显示和关闭事件移动事件调整大小事件鼠标事件进入和离开事件鼠标按下和释放事件鼠标双击事件鼠标按下移动事件 键盘事件焦点事件拖拽事件绘制事件改变事件右键菜单输入法 事件转发机制案例一案例二案例三 事件消息 显示和关闭事件 showEvent(QShowEvent)方法…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...