C++堆排序的实现(超详细)

C++:堆排序 目录 什么是堆排序: 堆排序步骤: 步骤一 、构造初始堆。将给定无序序列构造成一个大顶堆 步骤二 、将堆顶元素与末尾元素进行交换,使末尾元素最大。 最后结果: 再简单总结下堆排序的基本思路: 代码:  堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。 什么是堆排序:... 阅读详情

C++堆排序的实现完整代码

分享一篇讲解堆排序基本概念的文章,很生动形象:

https://mp.weixin.qq.com/s?__biz=MzIwNTc4NTEwOQ==&mid=2247484709&idx=2&sn=7bd9b16069d5a37f9ef521c33f947564

1、HeapSort.h

/* 初始版本,升序排序 */
/* 时间复杂度O(nlbn),空间复杂度O(1) */
/* 不稳定,如排序 5 7 13 5`
	建成大根堆 13 7 5 5`
	第一次排序并调整:7 5` 5 13
	第二次排序并调整:5 5` 7 13 (排序完成)
*/

#ifndef HEAPSORT_H
#define HEAPSORT_H

#include <iostream>
#include <stdlib.h>
// using namespace std;

/*
* 用以比较,
* a > b ,建立大根堆,升序排序
* a < b ,建立小根堆,降序排序
*/
bool cmp(const int &a, const int &b){
	return a > b;
}

/***************
* 传入的数组起始节点从0开始,对于下标为k的节点来说:
* 左孩子位置:2k + 1
* 右孩子位置:2k + 2
* 父亲节点位置:(k - 1) / 2
****************/

/*
* 上浮操作,比较节点与其父节点,满足条件则交换子和父的值
*/
void swim(int* const arr, const int &k){
	int parent = (k - 1) / 2;	// 求出待插入元素父节点的位置
	if(parent < 0 || arr == nullptr) return;	// 父节点不存在或者数组本身为空


	if(cmp(arr[k], arr[parent])){	// 该节点大于父节点
		std::swap(arr[k], arr[parent]);	// 交换节点值
		swim(arr, parent);	// 继续上浮
	}
}

/*
* 下沉操作,比较节点与其子节点,满足条件则交换子和父的值
* 如果是大根堆,节点应该与值大的子节点交换
* 如果是小根堆,节点应该与值小的子节点交换
*/
void sink(int* arr, const int &heapSize, const int &k){
	if(arr == nullptr) return;


	int maxOne = k;	// 保存最大节点的下标,初始为父节点


	int leftChild = 2 * k + 1;	// 求出左孩子的位置
	if(leftChild < heapSize) 	// 左孩子未越界
		maxOne = cmp(arr[leftChild], arr[k]) ? leftChild : k;	// 与左孩子节点比较,选取较大节点的下标


	int rightChild = 2 * k + 2;	// 求出右孩子的位置
	if(rightChild < heapSize)	// 右孩子未越界
		maxOne = cmp(arr[maxOne], arr[rightChild]) ? maxOne : rightChild;


	if(maxOne != k){
		std::swap(arr[k], arr[maxOne]);	// 值最大的节点不是该父节点,
		sink(arr, heapSize, maxOne);	// 该父节点继续下沉
	}
}

/*
* 删除堆根节点时,先与最后一个节点进行交换,交换后,堆大小减1,并对根节点进行下沉调整
*/
void deleteTop(int* arr, int &heapSize){
	std::swap(arr[0], arr[heapSize - 1]);
	--heapSize;
	sink(arr, heapSize, 0);
}

/*
* 每一个叶子节点可以看成一个大小唯一的堆
* 从最后一个非叶子节点(即最后一个节点的父节点)开始,对每一个节点进行下沉操作
* 这样以当前节点为根节点的树就变成堆了
*/
void buildHeap(int* arr, const int &heapSize){
	int i = (heapSize - 1) / 2;
	for( ; i >= 0; --i)
		sink(arr, heapSize, i);
}


void HeapSort(int* arr, int size){
	// 建大根堆,用以升序排序
	int heapSize = size;	// 为了删除的时候改变的不是原本size的值
	buildHeap(arr, size);
	// size 个元素的大根堆,排序(删除堆顶) size - 1 次, 数组就变成升序了
//	for(int i = 0; i < size; ++i)
//		std::cout << arr[i] << " ";
	for(int i = 0; i < size - 1; ++i){
		deleteTop(arr, heapSize);	// 删除堆顶会修改size的大小
	}
}

/*
* 时间复杂度分析:https://mp.weixin.qq.com/s?__biz=MzIwNTc4NTEwOQ==&mid=2247484709&idx=2&sn=7bd9b16069d5a37f9ef521c33f947564
* 建堆:O(n)
* 定义叶子节点高度为0,对于高为h的节点下沉代价为O(h)
* 堆中所有元素下沉代价之和就是建堆的代价(时间复杂度)
* n个元素的堆,高度为h的节点最多有[n/2^(h+1)]
* n个元素的堆高度为[lbn]
* 对于h = [0, lbn],求和Σ[n/2^(h+1)]O(n) = O(nΣh/2^(h+1)),让n趋于无穷,则lbn趋于无穷
* 对于0到无穷的Σ[h*x^h] = x/(1-x)^2
* 所以,对于0到无穷的Σ[h/2^(h+1)] = (1/2)/(1-1/2)^2 = 2
* 所以对于h = [0, lbn],求和Σ[n/2^(h+1)]O(n) = O(nΣh/2^(h+1)),结果为O(2n) = O(n)
* 删除:O(nlbn)
* n - 1次调用deleteTop
* deleteTop中包含swap和sink,swap代价为常数,sink代价为lbn
* 相当于进行了n - 1次sink
* 则共花费 (n-1)lbn,时间复杂度为O(nlbn)
*/

#endif // HEAPSORT_H

2、main.cpp

#include "HeapSort.h"

int main()
{
    int arr[] = {5, 13 ,7 ,5};
    HeapSort(arr, 4);

    for(int i = 0; i < 4; ++i)
        std::cout << arr[i] << " ";
    return 0;
}

排序不得不看之:C++快速排序的实现(注释超详细)

排序不得不看之:C++归并排序(注释超详细)

使用C++模版实现堆排序算法 合并排序具有较好的运行时间复杂度O(nlogn),但却需要额外的O(n)的空间;插入排序不需要开辟新的空间,但其时间开销却维持在O(n^2)。这两种算法各有所长,但都不尽如人意,综合看来:不是用时间买空间,就是用空间换时间。有没有这样一种集众家所长的算法?既保持一个较好的时间复杂度,又不必开辟额外的空间。堆排序无疑是不二选择。    以下即是用模版实现的堆排序的算法。 #include 阅读详情

相关推荐

堆排序算法(C++版)

堆排序(Heap Sort)是一种基于二叉堆数据结构的排序算法。它的基本思想是先将待排序的元素构建成一个二叉堆,然后依次将堆顶元素与堆中最后一个元素交换,调整堆,重复此过程直到整个数组有序。

WwLK123的博客 1748

C++实现排序算法之堆排序

一、算法思想 堆排序是利用堆性质进行的一种选择排序 概念: 堆:堆是一棵顺序存储的完全二叉树 每个节点的值都不大于其左右孩子节点的值的堆叫做小根堆(下左图) 每个节点的值都不小于其左右孩子节点的值的堆叫做大根堆(下右图) 设当前元素在数组中以R[i]表示,那么, (1) 它的左孩子结点是:R[2*i+1]; (2) 它的右孩子结点是:R[2*i+2]; (3) 它的父结点是:R[(i-1)/2]; (4) R[i] <= R[2*i+1] 且 R[i] <= R[2i+2]。 堆排序步骤如下:

qq_38307826的博客 4189

C++简单排序:堆排序

当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大根堆。优先队列具有队列的所有特性,包括基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的。, 它和queue不同的就在于我们可以自定义其中数据的优先级, 让优先级高的排在队列前面,优先出队。要学堆排序,首先要会优先队列。优先队列我就不打了,你们自己看以下内容。第一个是小根堆,是int类型。这里就定义了两个优先队列。是保证最小值在队列最前面,

小天狼星_布莱克 的博客 2063

C++堆排序(完整版)

堆排序步骤: (1)变为大顶堆;根节点的值大于等于其孩子节点的值。堆是一个完全二叉树,很适合用顺序结构来实现,这里我们选择数组。 (2)最后一个数据和最顶部节点数据交换(最大值放在最后),然后再进行一次调整(heapify函数),变为大顶堆(此时heapsize减1)。 #include &lt;iostream&gt; #include &lt;vector&gt; using name...

code进击者 3974

C++堆排序算法实现与分析

最大堆是一种特殊的完全二叉树,它满足任何一个父节点的值都大于或者等于其子节点的值。最大堆通常被用来实现优先队列和堆排序算法。在最大堆中,最大元素总是位于根节点,这使得访问最大元素非常高效。堆的根节点存储在数组的第一个位置,对于任何位于数组索引i的元素,它的左子节点的索引是2*i + 1,右子节点的索引是2*i + 2,而它的父节点索引则是(i-1) / 2。堆排序算法的C++实现可以通过一个主函数来控制整个流程。首先,我们需要初始化一个数组,这个数组将作为堆排序的对象。

weixin_42629522的博客 743

如何使用 Ansys OptiSlang 同时运行多个参数化设计研究

了解如何通过使用 OptiSLang 同时运行多个参数化设计研究来提高工作效率。

jkh920184196的博客 2379

C C++最全堆排序算法---C语言实现(超详细解析!!!!(1),字节跳动Andorid岗25k+的面试题

*✨思路:**首先,**我们把第一个数字看成堆,也就是4,当第二个数字插入进去的时候,进行向上调整算法,使其确保为小堆,**向上调整的算法在上篇博文已详细讲解过,不过多赘述。当我们找到这个非叶结点时,把它和它的孩子看成一个整体,进行向下调整。调整后,再将次父节点向前挪动,再次向下调整,依次循环下去。(img-4PLMb0PZ-1715705908165)]**此段代码的时间复杂度为O(N*logN),****此段的时间复杂度同样为O(N*logN),****✨:****分析:**从该解决方案中,

2401_84976700的博客 564

数电-基于FPGA的自动售货控制系统设计

本次数电的课程设计是设计一款基于FPGA的自动售货控制系统,因为手上暂时没有FPGA的板子,所以先采用proteus仿真进行设计,观察系统效果,等之后FPGA板子下发,再移到quartus上调试和下载。同样是自己第一次自主设计电路系统,可能在功能上不完整或者逻辑上有错误,大家多多包涵,欢迎沟通交流。

gg1067的博客 2289

堆排序——C++实现

堆是完全二叉树的结构,因此对于一个有n个节点的堆,高度为O(logn),二叉堆是采用数组的方式来存储的,分为大顶堆和小顶堆两种: 大顶堆:根节点大于等于自己的两个孩子节点。 小顶堆:根节点小于等于自己的两个孩子节点。 堆排序总共分为两步: 1、初始化建堆: 找到一个树的最后一个非叶节点, 计算公式为 (n-1)/2 -1, 然后遍历树的每个非叶节点,使其符合堆的规则。 2、排序重建堆: 将堆的...

EricLee23 4426

避坑!瑞萨RZ/N2L用J-Link下载调试的那些‘坑’(从驱动版本到硬件架构选择)

本文详细解析了瑞萨RZ/N2L开发中使用J-Link调试时常见的兼容性问题与解决方案,包括驱动版本选择、SWD连接优化及e2 studio调试技巧。特别针对硬件架构与驱动版本的匹配问题提供了实用对照表,帮助开发者高效避开调试陷阱,提升开发效率。

weixin_30576827的博客 441

ESP32S3电池电量监测实战:从分压电路到IDF组件配置(附GitHub源码)

本文详细介绍了ESP32S3电池电量监测的完整实战方案。从硬件分压电路的电阻选型、滤波设计,到软件层面利用ESP-IDF的ADC校准机制提升精度,并重点讲解了如何集成bat_monitor开源组件快速实现电压采集、电量计算、充电检测与事件通知。文章提供了从原理到调试的完整指南和GitHub源码,帮助开发者构建稳定可靠的物联网设备电源管理系统。

ee345的博客 529

C++堆排序的原理及实现

首先回顾下堆的数据结构的特点: 堆的描述 堆是一颗二叉树,这样的二叉树是局部有序的,任何节点与其兄弟节点之间都没有必然的顺序联系,但是它与父子节点之间有大小顺序关系,按照关系的不同,分为最大值堆和最小值堆: 最大值堆:子节点比父节点小的堆,根节点是树中最大的节点。 最小值堆:子节点比父节点大的堆,根节点是树中最小的节点。 堆是左平衡的树,所以随着节点的增加,树会逐级从左至右增长。因此对于一个堆来说,一个比较好的表示左平衡二叉树的方式是: 将节点通过水平遍历的方式连续存储到一个数组中。假设有一个零

DayDayUp 4042

CIFAR-100模型性能对比:Top1与Top5错误率深度解析

本文深度解析了CIFAR-100数据集上Top1与Top5错误率的核心意义与差异。通过对比MobileNet、ResNet、DenseNet等主流模型的性能数据,揭示了模型架构、训练策略及数据集特性如何共同影响这两个关键指标,并为不同应用场景下的模型选择提供了实战指南。

weixin_28224217的博客 335

CPP 实现堆排序

int Swap(int &a,int &b) { int temp=a; a=b; b=temp; } void Heap_build(int a[],int root,int length) { int lchild=root*2+1; if(lchild<length) { int flag=lchild;...

跟随内心的渴望 777

uniapp - 实现APP后台持续定位+手机息屏后能持续上传位置信息数据,详解后台保活持续运行+手机锁屏保证后台持续/实时定位的解决方案及示例源码(完美兼容安卓android与苹果ios系统手机)

使用uniapp开发app实现后台保活定位能力,uniapp实时定位保活 息屏定位后台运行,uniapp APP实时定位高德 后台运行 支持锁屏息屏运行,持续获取定位信息,uniapp App端后台间隔时间发送定位功能实现,UniApp实现手机应用常活,固定时间内上传手机位置信息,后台(或锁屏)持续/实时定位的实现方案,uni-app后台持续定位,锁屏后能持续上传位置信息,实现后台定位持续无限制定位高德定位,百度定位,UniApp后台持续定位保如何在APP退到后台时保持定位服务,uniapp 切换app仍能

🏆 前端领域优质创作者 1万+

【AUTOSAR-DEM】-2.4-APP SWC如何读取MIL灯状态以及配置MIL灯

该篇博文将告诉您: MIL(Malfunction Indicator Lamp/Light)灯的点灯和灭灯过程; DEM模块如何配置MIL灯; APP SWC如何获取MIL灯状态。

「汽车电子助手」的博客 1709

c++十大排序——堆排序

1、堆排序 堆排序采用堆的这种数据结构,堆首先是一颗完全二叉树。 堆又分为大顶堆和小顶堆 大顶堆就是父节点数值大于等于左右节点数值 小顶堆是父节点数值小于等于左右节点数值 下标为i的节点的父节点下表为:(i-1)/2 下标为i的节点的左孩子下表为:i*2+1 下标为i的节点的右孩子下表为:i*2-1 #include<iostream> using namespace std; void sw(int &a,int &b) { int temp

yang_yi520的博客 1万+

14.建立时间、保持时间以及vivado时序report的参考使用

在设计数字系统时,需要仔细考虑电路元件的选择和布局以及时序设计来满足建立时间和保持时间的要求。建立时间,又称为建立时间窗口或建立期,是指数字信号在触发器的时钟信号前沿到来之前,必须已经稳定存在的时间。在本章节将结婚扫建立时间和保持时间的基本原理,以及如何通过vivado处理建立时间和保持时间。通过使用同步电路,可以更好地控制数据传输的时序并满足建立时间和保持时间的要求。例如,在D触发器中,选择具有适当充电和放电特性的D端口元件可以确保在时钟信号前沿到达前数据已经稳定存在,并在时钟信号前沿到达后保持稳定。

FPGA/MATLAB学习教程/源码/项目合作开发 2984

经典排序算法之堆排序详解|c++代码实现|什么是堆排序|如何代码实现堆排序

经典排序算法之堆排序详解|c++代码实现|什么是堆排序|如何代码实现堆排序

qq_64431512的博客 3095

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

C++实现堆排序

C++实现堆排序

weixin_59566851的博客 5515

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

C++堆排序

堆排序(Heap Sort)是一种基于二叉堆数据结构的比较排序算法,它是一种选择排序,可分为最大堆排序和最小堆排序,以下主要介绍最大堆排序。二叉堆的定义:堆排序的步骤: 代码解释 函数: 函数: 函数: 函数:堆排序是一种高效的排序算法,尤其适用于处理大量数据的情况,它在性能上较为稳定,并且不需要额外的存储空间。

doubleintfloat的博客 1516

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

堆排序(递归)C++实现

堆排序(递归)C++实现 堆排序 使用堆的数据结构来进行排序,堆可以看成一个近似完全二叉树的顺序存储结构的数组 维护堆性质 维护堆的性质,对于给定的下标i,以i结点为根节点的堆左右子树都是最大堆,此时i对应结点的关键字可能小于其孩子节点,则违背了堆性质,通过向下调整使得这个堆满足最大堆的性质 堆调整算法选取根节点左右孩子关键字较大值与根节点交换,再递归进入被交换的左右孩子为根节点的堆,继续向下调整,直到当前的堆满足最大堆性质或者调整到叶子节点。 C++代码 void MaxHeap::maxHeapif

qq_44486439的博客 1166

堆排序的C++代码实现

堆排序C++实现 堆排序的具体思路可以查看《算法导论》这本书,一下只提供笔者的C++实现代码,并且将笔者在编写程序的过程当中所遇到的一些细节问题拿出来作一番解释,希望能够对对堆排序有一个透彻的理解。 1、构造一个维护堆性质(最大堆)的函数 这里需要做一个假设:对于数组中下标为i的节点其左子树和右子树都是保持最大堆性质的堆。在假设成立的前提上,经过这一个维护函数维护过...

LingTing00101的博客 419

堆排序C++实现

堆排序C++实现 实现代码 最大堆 /* * @Author: eclipse * @Email: eclipsecs@qq.com * @Date: 2020-05-18 17:56:49 * @Last Modified by: eclipse * @Last Modified time: 2020-05-18 19:15:36 */ #include<bits/stdc++.h> using namespace std; class MaxHeap { private:

qq_44486439的博客 481

【堆排序】-详细例子以及C++实现

文章目录1. 堆2. 堆排序2.1 步骤2.2 举例3. 程序实现4. 参考资料 这里的根节点从1开始编号!! 1. 堆 堆是一棵完全二叉树 大根堆: 任何一个父节点的值不小于其左右孩子结点的值,即: key[i]≥key[2i]&&key[i]≥key[2i+1] key[i] \geq key[2i] \quad \&\& \quad key[i] \geq key[2i+1] key[i]≥key[2i]&&key[i]≥key[2i+1] 堆顶元素

学无止境 1418
上一篇: C++快速排序的实现(注释超详细)
下一篇: python小应用之moviepy的视频剪辑制作gif图
Spade_
博客等级 码龄10年 918粉丝 123原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值