每日一题——小根堆实现堆排序算法
小根堆实现堆排序算法
- 堆排序的基本思想
- 堆排序的步骤
- 实现步骤
- 1. 构建小根堆
- 2. 删除最小元素并调整堆
- C语言实现
- 输出示例
- 代码解释
- 1. percolateDown 函数
- 2. buildMinHeap 函数
- 3. heapSort 函数
- 4. printArray函数
- 排序过程详解
- 步骤1:构建小根堆
- 步骤2:删除堆顶元素并调整堆
- 最终结果
- 总结
堆排序是一种基于堆数据结构的排序算法,利用堆的性质来高效地对数组进行排序。堆排序的时间复杂度为 O ( n log n ) O(n\log n) O(nlogn),而且是一种原地排序算法,空间复杂度为 O ( 1 ) O(1) O(1)。
堆排序的基本思想
堆排序的核心思想是利用小根堆的性质,将数组构建成一个小根堆,然后逐步删除堆顶元素(最小值),并将其放到数组的末尾。通过重复这个过程,数组最终会被排序。
堆排序的步骤
- 构建小根堆:将数组构建成一个小根堆。
- 删除最小元素:每次删除堆顶元素(最小值),并将堆的最后一个元素移到堆顶,然后调整堆以保持小根堆的性质。
- 重复步骤2:直到堆为空,此时数组已经被排序。
实现步骤
1. 构建小根堆
从最后一个非叶子节点开始,逐个向下调整,直到根节点。最后一个非叶子节点的索引为 $ \left\lfloor \frac{2n - 2}{2} \right\rfloor $,其中 n n n 是数组的长度。
2. 删除最小元素并调整堆
每次删除堆顶元素,将其放到数组的末尾,然后将堆的最后一个元素移到堆顶,再进行向下调整。
C语言实现
#include <stdio.h>
#include <stdlib.h>// 向下调整堆
void percolateDown(int* arr, int n, int i) {int smallest = i; // 当前节点索引int left = 2 * i + 1; // 左子节点索引int right = 2 * i + 2; // 右子节点索引//找到父子结点中的最小节点索引// 如果左子节点存在且小于当前节点的值if (left < n && arr[left] < arr[smallest]) smallest = left;// 如果右子节点存在且小于当前最小值if (right < n && arr[right] < arr[smallest])smallest = right;// 如果最小值不是当前节点,交换并继续调整堆if (smallest != i) {int temp = arr[i];arr[i] = arr[smallest];arr[smallest] = temp;percolateDown(arr, n, smallest); // 递归调整}
}// 构建小根堆
void buildMinHeap(int* arr, int n) {// 从最后一个**非叶子节点**开始调整后一大半都是叶子节点for (int i = (n - 2) / 2; i >= 0; i--) {percolateDown(arr, n, i);}
}// 堆排序
void heapSort(int* arr, int n) {// 构建小根堆buildMinHeap(arr, n);// 逐个删除最小元素并调整堆for (int i = n - 1; i >= 0; i--) {// 将堆顶元素(最小值)放到数组末尾int temp = arr[0];arr[0] = arr[i];arr[i] = temp;// 调整剩余的堆percolateDown(arr, i, 0);}
}// 打印数组
void printArray(int* arr, int n) {for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");
}int main() {int arr[] = {3, 1, 6, 5, 2, 4}; // 待排序数组int n = sizeof(arr) / sizeof(arr[0]);printf("Original array: ");printArray(arr, n);heapSort(arr, n); // 执行堆排序printf("Sorted array: ");printArray(arr, n); // 输出排序后的数组return 0;
}
输出示例
运行上述代码,输出如下:
Original array: 3 1 6 5 2 4
Sorted array: 1 2 3 4 5 6
代码解释
1. percolateDown 函数
这个函数用于向下调整堆,确保当前节点的值小于其子节点的值。通过比较当前节点、左子节点和右子节点的值,找到最小值的索引。如果最小值不是当前节点,交换它们,并递归调整子树。
2. buildMinHeap 函数
从最后一个非叶子节点开始,逐个向下调整,直到根节点。最后一个非叶子节点的索引为 ⌊ 2 n − 2 2 ⌋ \left\lfloor \frac{2n - 2}{2} \right\rfloor ⌊22n−2⌋。
3. heapSort 函数
首先调用 buildMinHeap
构建小根堆。然后逐个删除堆顶元素(最小值),将其放到数组末尾。每次删除后,调整剩余的堆,确保堆的性质仍然成立。
4. printArray函数
该函数用于打印数组,方便查看排序结果。
排序过程详解
假设我们有一个数组 arr[] = {3, 1, 6, 5, 2, 4}
,以下是堆排序的详细过程:
步骤1:构建小根堆
- 构建小根堆:从最后一个非叶子节点开始向下调整,直到根节点。
arr[] = {3, 1, 6, 5, 2, 4}
- 从索引
2
(值为6
)开始:- 左子节点
5
,右子节点4
,最小值为4
,交换6
和4
,调整得到arr[] = {3, 1, 4, 5, 2, 6}
。
- 左子节点
- 继续调整索引
1
(值为1
):- 左子节点
5
,右子节点2
,最小值为2
,交换1
和2
,调整得到arr[] = {3, 2, 4, 5, 1, 6}
。
- 左子节点
- 最后调整索引
0
(值为3
):- 左子节点
2
,右子节点4
,最小值为2
,交换3
和2
,调整得到arr[] = {2, 3, 4, 5, 1, 6}
。 - 接着,索引
1
的值为3
,继续向下调整,最终得到arr[] = {2, 1, 4, 5, 3, 6}
。
- 左子节点
此时,堆构建完成。
步骤2:删除堆顶元素并调整堆
- 删除堆顶元素并调整堆:
- 第一次:
- 删除堆顶元素
2
,将堆顶替换为堆的最后一个元素6
,得到arr[] = {6, 1, 4, 5, 3}
。 - 调整堆,交换
6
和1
,然后交换6
和3
,得到arr[] = {1, 3, 4, 5, 6}
。
- 删除堆顶元素
- 第二次:
- 删除堆顶元素
1
,将堆顶替换为堆的最后一个元素6
,得到arr[] = {6, 3, 4, 5}
。 - 调整堆,交换
6
和3
,得到arr[] = {3, 6, 4, 5}
,然后交换6
和5
,得到arr[] = {3, 5, 4, 6}
。
- 删除堆顶元素
- 第三次:
- 删除堆顶元素
3
,将堆顶替换为堆的最后一个元素6
,得到arr[] = {6, 5, 4}
。 - 调整堆,交换
6
和4
,得到arr[] = {4, 5, 6}
。
- 删除堆顶元素
- 第四次:
- 删除堆顶元素
4
,将堆顶替换为堆的最后一个元素6
,得到arr[] = {6, 5}
。 - 调整堆,交换
6
和5
,得到 `arr[] =
- 删除堆顶元素
- 第一次:
{5, 6}`。
- 第五次:
- 删除堆顶元素
5
,将堆顶替换为堆的最后一个元素6
,得到arr[] = {6}
。 - 此时,堆中只剩一个元素,排序完成。
- 删除堆顶元素
最终结果
排序后的数组为 arr[] = {1, 2, 3, 4, 5, 6}
。
总结
堆排序利用小根堆的性质,通过构建堆、删除堆顶元素并调整堆的方式进行排序。它的时间复杂度为 O ( n log n ) O(n\log n) O(nlogn),空间复杂度为 O ( 1 ) O(1) O(1),是一种原地排序算法,不稳定排序适用于大规模数据的排序任务。
相关文章:
每日一题——小根堆实现堆排序算法
小根堆实现堆排序算法 堆排序的基本思想堆排序的步骤 实现步骤1. 构建小根堆2. 删除最小元素并调整堆 C语言实现输出示例代码解释1. percolateDown 函数2. buildMinHeap 函数3. heapSort 函数4. printArray函数 排序过程详解步骤1:构建小根堆步骤2:删除堆…...
k8s集群
文章目录 项目描述项目环境系统与软件版本概览项目步骤 环境准备IP地址规划关闭selinux和firewall配置静态ip地址修改主机名添加hosts解析 项目步骤一、使用kubeadm安装k8s单master的集群环境(1个master2个node节点)1、互相之间建立免密通道2.关闭交换分…...
数据分析系列--[11] RapidMiner,K-Means聚类分析(含数据集)
一、数据集 二、导入数据 三、K-Means聚类 数据说明:提供一组数据,含体重、胆固醇、性别。 分析目标:找到这组数据中需要治疗的群体供后续使用。 一、数据集 点击下载数据集 二、导入数据 三、K-Means聚类 Ending, congratulations, youre done....
技术架构师成长路线(2025版)
目录 通用知识 计算机原理(1 - 2 个月) 数据结构(2 - 3 个月) 网络编程(1 - 2 个月) 软件工程(1 个月) 基础知识 Java 编程语言基础(2 - 3 个月) JVM&…...
NetLify账号无法登录解决办法
本文收录在【建站】专栏内,专栏目录:【建站】专栏目录 用github账号登录时,说校验失败 Authentication Error Authenticating failed due to the following error: Your account requires additional verification. Please check your email…...
linux本地部署deepseek-R1模型
国产开源大模型追平甚至超越了CloseAI的o1模型,大国崛起时刻!!! DeepSeek R1 本地部署指南 在人工智能技术飞速发展的今天,本地部署AI模型成为越来越多开发者和企业关注的焦点。本文将详细介绍如何在本地部署DeepS…...
集合通讯概览
集合通信概览 (1)通信的算法 是根据通讯的链路组成的 (2)因为通信链路 跟硬件强相关,所以每个CCL的库都不一样 芯片与芯片、不同U之间是怎么通信的 多卡训练:多维并行(xxx并行在上一期已经讲述…...
如何解决云台重力补偿?
如何解决云台重力补偿? 最近在调试步兵云台的时候,由于枪管、图传、摄像头等重力的原因,pitch轴的参数尤其难以调整,又不想抬升和降低使用两套不同的参数,所以使用了重力补偿,效果也是比较理想的,于是整理为一篇文章记录一下 一、问题根源:枪管重力在“搞事情” 想象…...
【LeetCode 刷题】回溯算法(4)-排列问题
此博客为《代码随想录》二叉树章节的学习笔记,主要内容为回溯算法排列问题相关的题目解析。 文章目录 46.全排列47.全排列 II 46.全排列 题目链接 class Solution:def permute(self, nums: List[int]) -> List[List[int]]:res, path [], []used [0] * len(n…...
FPGA|IP核PLL调用测试:建立工程
闲来无事,测试下FPGA的IP核调用 一、生成工程 1、打开软件新建工程 2、命名为PLL_test 3、选择芯片型号 4、生成工程如图...
数据的表示和运算
一-定点数的表示 1-定点数和浮点数 定点数:小数点的位置固定(常规计数) 浮点数:小数点的位置不固定(科学计数法) 2-定点数的表示 ①无符号数 整个机器字长的全部二进制位均为数值位,没有符号…...
文字显示省略号
多行文本溢出显示省略号...
22.Word:小张-经费联审核结算单❗【16】
目录 NO1.2 NO3.4 NO5.6.7 NO8邮件合并 MS搜狗输入法 NO1.2 用ms打开文件,而不是wps❗不然后面都没分布局→页面设置→页面大小→页面方向→上下左右:页边距→页码范围:多页:拼页光标处于→布局→分隔符:分节符…...
鲸鱼算法 matlab pso
算法原理 鲸鱼优化算法的核心思想是通过模拟座头鲸的捕食过程来进行搜索和优化。座头鲸在捕猎时会围绕猎物游动并产生气泡网,迫使猎物聚集。这一行为被用来设计搜索策略,使算法能够有效地找到全局最优解。 算法步骤 初始化:随机生成一…...
c++之模板进阶
在前面的文章中,我们已经简单的了解了模板的使用,在这篇文章中,我们将继续深入探讨模板 1.模板的特化 1.1 概念 通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果&a…...
C语言中的信号量
信号是操作系统中用来传递特定消息的机制。操作系统可以使用这种方式将程序运行过程中发生的各类特殊情况发送给程序,并按照其指定的逻辑进行处理。信号名称都以 “SIG” 作为前缀,如程序访问非法内存时,会产生名为 SIGSEGV 的信号。 程序需…...
AI主流大模型介绍和API价格比较
主流的大模型系列 ###1. OpenAI: GPT-4,GPT-4 Turbo, GPT-4o OpenAI 的介绍: 全称:Open Artificial Intelligence,简称OpenAI。性质:起初为非营利性组织,后转变为由营利性公司OpenAI LP及非营…...
自主Shell命令行解释器
什么是命令行 我们一直使用的"ls","cd","pwd","mkdir"等命令,都是在命令行上输入的,我们之前对于命令行的理解: 命令行是干啥的?是为我们做命令行解释的。 命令行这个东西实际上是我们…...
git笔记-简单入门
git笔记 git是一个分布式版本控制系统,它的优点有哪些呢?分为以下几个部分 与集中式的版本控制系统比起来,不用担心单点故障问题,只需要互相同步一下进度即可。支持离线编辑,每一个人都有一个完整的版本库。跨平台支持…...
重新刷题求职2-DAY1
DAY1 1.704. 二分查找 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。 最普通的二分查找,查用的习惯左闭右…...
浅析DDOS攻击及防御策略
DDoS(分布式拒绝服务)攻击是一种通过大量计算机或网络僵尸主机对目标服务器发起大量无效或高流量请求,耗尽其资源,从而导致服务中断的网络攻击方式。这种攻击方式利用了分布式系统的特性,使攻击规模更大、影响范围更广…...
路径规划之启发式算法之二十九:鸽群算法(Pigeon-inspired Optimization, PIO)
鸽群算法(Pigeon-inspired Optimization, PIO)是一种基于自然界中鸽子群体行为的智能优化算法,由Duan等人于2014年提出。该算法模拟了鸽子在飞行过程中利用地标、太阳和磁场等导航机制的行为,具有简单、高效和易于实现的特点,适用于解决连续优化问题。 更多的仿生群体算法…...
SwiftUI 在 Xcode 预览修改视图 FetchedResults 对象的属性时为什么会崩溃?
概览 从 SwiftUI 诞生那天起,让秃头码农们又爱又恨的 Xcode 预览就在界面调试中扮演了及其重要的角色。不过,就是这位撸码中的绝对主角却尝尝在关键时刻“掉链子”。 比如当修改 SwiftUI 视图中 FetchedResults 对象的属性时,Xcode 预览可能…...
pytorch实现基于Word2Vec的词嵌入
PyTorch 实现 Word2Vec(Skip-gram 模型) 的完整代码,使用 中文语料 进行训练,包括数据预处理、模型定义、训练和测试。 1. 主要特点 支持中文数据,基于 jieba 进行分词 使用 Skip-gram 进行训练,适用于小数…...
MVC 文件夹:架构之美与实际应用
MVC 文件夹:架构之美与实际应用 引言 MVC(Model-View-Controller)是一种设计模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种架构模式不仅提高了代码的可维护性和可扩展性,而且使得开发流程更加清晰。本文将深入探讨MVC文…...
Python在线编辑器
from flask import Flask, render_template, request, jsonify import sys from io import StringIO import contextlib import subprocess import importlib import threading import time import ast import reapp Flask(__name__)RESTRICTED_PACKAGES {tkinter: 抱歉&…...
The Simulation技术浅析(四):随机数生成
随机数生成技术 是 The Simulation 中的核心组成部分,广泛应用于蒙特卡洛模拟、密码学、统计建模等领域。随机数生成技术主要分为 伪随机数生成器(PRNG,Pseudo-Random Number Generator) 和 真随机数生成器(TRNG,True Random Number Generator)。 1. 伪随机数生成器(PR…...
centos stream 9 安装 libstdc++-static静态库
yum仓库中相应的镜像源没有打开,libstdc-static在CRB这个仓库下,但是查看/etc/yum.repos.d/centos.repo,发现CRB镜像没有开启。 解决办法 如下图开启CRB镜像, 然后执行 yum makecache yum install glibc-static libstdc-static…...
Java自定义IO密集型和CPU密集型线程池
文章目录 前言线程池各类场景描述常见场景案例设计思路公共类自定义工厂类-MyThreadFactory自定义拒绝策略-RejectedExecutionHandlerFactory自定义阻塞队列-TaskQueue(实现 核心线程->最大线程数->队列) 场景1:CPU密集型场景思路&…...
Shell $0
个人博客地址:Shell $0 | 一张假钞的真实世界 我们已经知道在Shell中$0表示Shell脚本的文件名,但在有脚本调用的情形中,子脚本中的$0会是什么值呢?我们通过下面的实例来看。 已测试系统列表: Mac OS X EI Capitan 1…...
C++ Primer 标准库类型string
欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...
51c嵌入式~电路~合集25
我自己的原文哦~ https://blog.51cto.com/whaosoft/13241709 一、“开关电源”和“普通电源”的区别 什么叫开关电源 随着电力电子技术的发展和创新,使得开关电源技术也在不断地创新。目前,开关电源以小型、轻量和高效率的特点被广泛应用几乎所有的电…...
Vue3学习笔记-Vue开发前准备-1
一、安装15.0或更高版本的Node.js node -v npm -v 二、创建Vue项目 npm init vuelatest 三、Vue项目结构 node_modules: Vue项目运行的依赖文件public:资源文件夹package.json:信息描述文件...
架构技能(四):需求分析
需求分析,即分析需求,分析软件用户需要解决的问题。 需求分析的下一环节是软件的整体架构设计,需求是输入,架构是输出,需求决定了架构。 决定架构的是软件的所有需求吗?肯定不是,真正决定架构…...
51单片机 05 矩阵键盘
嘻嘻,LCD在RC板子上可以勉强装上,会有一点歪。 一、矩阵键盘 在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式;采用逐行或逐列的“扫描”,就可以读出任何位置按键的状态。…...
服务SDK三方新版中央仓库和私服发布详解
预备信息Github仓库发布Gradle版本匹配Gradle项目构建全局变量定义Gradle项目Nexus仓库配置与发布过程Gradle项目发布至Sonatype中央仓库配置过程总结当我们在实现一个项目技术总结、工具类封装或SDK封装,通常是为了方便开发者使用特定服务或平台而提供的一组工具和API。您可能…...
jmeter响应数据编码设置
jmeter响应数据编码设置 如果查看结果树的响应数据存在中文乱码,可以尝试以下方法: 1、找到jmeter的bin目录下的 jmeter.properties 文件,修改如下配置: 去掉sampleresult.default.encodingUTF-8前面的#号 2、保存文件后&#x…...
FPGA学习篇——开篇之作
今天正式开始学FPGA啦,接下来将会编写FPGA学习篇来记录自己学习FPGA 的过程! 今天是大年初六,简单学一下FPGA的相关概念叭叭叭! 一:数字系统设计流程 一个数字系统的设计分为前端设计和后端设计。在我看来࿰…...
Leetcode:680
1,题目 2,思路 首先就是判断它不发生改变会不会是回文如果不是回文,那么俩个指针从前往后与从后往前做对比如果俩字符不同,那就俩种选择,一种是保留前面的字符去掉后面字符,另一种是其反然后俩种选择只要满…...
Python教学:文档处理及箱线图等
代码1: import os import pandas as pd import numpy as py import os.path from os import listdir import openpyxl from openpyxl import Workbook import re import matplotlib.pyplot as plt # 导入matplotlib的绘图模块,用于可视化 cwdos.getcwd…...
SQLGlot:用SQLGlot解析SQL
几十年来,结构化查询语言(SQL)一直是与数据库交互的实际语言。在一段时间内,不同的数据库在支持通用SQL语法的同时演变出了不同的SQL风格,也就是方言。这可能是SQL被广泛采用和流行的原因之一。 SQL解析是解构SQL查询…...
C++STL(一)——string类
目录 一、string的定义方式二、 string类对象的容量操作三、string类对象的访问及遍历操作四、string类对象的修改操作五、string类非成员函数 一、string的定义方式 string是个管理字符数组的类,其实就是字符数组的顺序表。 它的接口也是非常多的。本章介绍一些常…...
C++ Primer 迭代器
欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...
排序算法--归并排序
归并排序是分治法的经典实现,适合大规模数据排序,尤其适合需要稳定排序的场景(如数据库排序) #include <stdlib.h> // 用于动态内存分配 // 合并两个已排序的子数组 void merge(int arr[], int left, int mid, int right) …...
深入探讨DICOM医学影像中的WADO服务及其具体实现
1. 引言 随着数字化医学影像技术的普及,如何高效、安全地存储、管理和共享医学影像数据成为医疗行业亟待解决的关键问题。DICOM(Digital Imaging and Communications in Medicine)作为国际公认的医学影像标准,在全球范围内广泛应…...
自定义数据集 使用paddlepaddle框架实现逻辑回归
导入必要的库 import numpy as np import paddle import paddle.nn as nn 数据准备: seed1 paddle.seed(seed)# 1.散点输入 定义输入数据 data [[-0.5, 7.7], [1.8, 98.5], [0.9, 57.8], [0.4, 39.2], [-1.4, -15.7], [-1.4, -37.3], [-1.8, -49.1], [1.5, 75.6…...
信息学奥赛一本通 2112:【24CSPJ普及组】地图探险(explore) | 洛谷 P11228 [CSP-J 2024] 地图探险
【题目链接】 ybt 2112:【24CSPJ普及组】地图探险(explore) 洛谷 P11228 [CSP-J 2024] 地图探险 【题目考点】 1. 模拟 2. 二维数组 3. 方向数组 在一个矩阵中,当前位置为(sx, sy),将下一个位置与当前位置横纵坐…...
xxl-job 在 Java 项目的使用 以一个代驾项目中的订单模块举例
能搜到这里的最起码一定知道 xxl-job 是用来干什么的,我就不多啰嗦怎么下载以及它的历史了 首先我们要知道 xxl-job 这个框架的结构,如下图: xxl-job-master:xxl-job-admin:调度中心xxl-job-core:公共依赖…...
javaEE-8.JVM(八股文系列)
目录 一.简介 二.JVM中的内存划分 JVM的内存划分图: 堆区:编辑 栈区:编辑 程序计数器:编辑 元数据区:编辑 经典笔试题: 三,JVM的类加载机制 1.加载: 2.验证: 3.准备: 4.解析: 5.初始化: 双亲委派模型 概念: JVM的类加…...
模型/O功能之提示词模板
文章目录 模型/O功能之提示词模板什么是提示词模板提示词模板的输入和输出 使用提示词模板构造提示词 模型/O功能之提示词模板 在LangChain框架中,提示词不是简单的字符串,而是一个更复杂的结构,是一个“提示词工程”。这个结构中包含一个或多…...