了解C++中STL的堆操作:构建、拆解和排序 堆(Heap)

2024-05-14 09:44

本文主要是介绍了解C++中STL的堆操作:构建、拆解和排序 堆(Heap),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在C++中使用STL构建、拆解和排序堆

  • 一、简介
  • 二、std::push_heap
  • 三、std::pop_heap
  • 四、std::sort_heap
  • 五、总结

一、简介

首先要要熟悉堆(Heap)是什么以及它们是如何工作的,如果你不知道什么是堆(Heap),可以先阅读前面的文章,再来看这篇文章会更好。

好了,现在假设你已经清楚堆(Heap),可以使用C++的STL来构建堆、拆解堆和对堆进行排序。

以一个堆(Heap)的例子开始:
在这里插入图片描述

这是一个最大堆,最大的元素在顶部。我们将插入一个元素(这与C++并没有太大关系),它是如何在堆数据结构中插入一个元素。

二、std::push_heap

在堆的末尾添加8.8。这并不是它正确的位置,所以将使它通过堆向上移动。将它与其父元素进行比较,每当它大于其父元素时,就对它们进行交换:
堆 C++ STL

这样它最终会到达它的最终位置。

在C++中,堆被表示为连续的结构,例如在std::vector中。因此,将这个堆压缩成一个数组。

现在要添加一个元素,将在向量的末尾push_back这个元素,并调用std::push_heap,使这个最后一个元素向其最终位置在堆中向上移动:

std::vector myHeap = // ... 有关std::make_heap,请参见前面的文章
myHeap.push_back(8.8);
std::push_heap(begin(myHeap), end(myHeap));

三、std::pop_heap

那么如何从堆中删除一个元素?只能删除一个元素,即顶部的元素。为了做到这一点,可以使用std::pop_heap。它首先将想要删除的第一个元素与最小的其中一个元素(即最后一个元素)进行交换。

然后,它将使这个小元素在堆中向下移动到其最终位置,通过与其子元素进行比较。每当它小于其中一个子元素时,将它与其最大的子元素交换,以确保能够保持堆的特性。
堆 C++ STL

为了实际去掉曾经在堆顶的元素,它现在位于verctor中的最后位置,在vector上执行一个pop_back

std::pop_heap(begin(myHeap), end(myHeap));
myHeap.pop_back();

四、std::sort_heap

仔细思考以下,如果重复执行std::pop_heap操作但不把vector中的元素取出来,那么顶部的元素就会按排序顺序堆积在vector的末尾。
这样做的次数越多,堆中的元素就越多,最终得到的是一个排序好的vector,不再有堆(Heap)。

这基本上是std::sort_heap所做的事情:

std::sort_heap(begin(myHeap), end(myHeap));

它接收一个堆并对其进行排序,其复杂度最大为2*N*log(N)

五、总结

以上就是使用STL操纵堆(Heap)的全部内容。这里看到了如何使用std::push_heap构建堆,如何使用std::pop_heap拆解堆,以及如何使用std::sort_heap对堆进行排序。

在这里插入图片描述

这篇关于了解C++中STL的堆操作:构建、拆解和排序 堆(Heap)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/988413

相关文章

利用c++判断水仙花数并输出示例代码

《利用c++判断水仙花数并输出示例代码》水仙花数是指一个三位数,其各位数字的立方和恰好等于该数本身,:本文主要介绍利用c++判断水仙花数并输出的相关资料,文中通过代码介绍的非常详细,需要的朋友可以... 以下是使用C++实现的相同逻辑代码:#include <IOStream>#include <vec

基于C++的UDP网络通信系统设计与实现详解

《基于C++的UDP网络通信系统设计与实现详解》在网络编程领域,UDP作为一种无连接的传输层协议,以其高效、低延迟的特性在实时性要求高的应用场景中占据重要地位,下面我们就来看看如何从零开始构建一个完整... 目录前言一、UDP服务器UdpServer.hpp1.1 基本框架设计1.2 初始化函数Init详解

C++ 右值引用(rvalue references)与移动语义(move semantics)深度解析

《C++右值引用(rvaluereferences)与移动语义(movesemantics)深度解析》文章主要介绍了C++右值引用和移动语义的设计动机、基本概念、实现方式以及在实际编程中的应用,... 目录一、右值引用(rvalue references)与移动语义(move semantics)设计动机1

MySQL游标和触发器的操作流程

《MySQL游标和触发器的操作流程》本文介绍了MySQL中的游标和触发器的使用方法,游标可以对查询结果集进行逐行处理,而触发器则可以在数据表发生更改时自动执行预定义的操作,感兴趣的朋友跟随小编一起看看... 目录游标游标的操作流程1. 定义游标2.打开游标3.利用游标检索数据4.关闭游标例题触发器触发器的基

在C#中分离饼图的某个区域的操作指南

《在C#中分离饼图的某个区域的操作指南》在处理Excel饼图时,我们可能需要将饼图的各个部分分离出来,以使它们更加醒目,Spire.XLS提供了Series.DataFormat.Percent属性,... 目录引言如何设置饼图各分片之间分离宽度的代码示例:从整个饼图中分离单个分片的代码示例:引言在处理

Python列表的创建与删除的操作指南

《Python列表的创建与删除的操作指南》列表(list)是Python中最常用、最灵活的内置数据结构之一,它支持动态扩容、混合类型、嵌套结构,几乎无处不在,但你真的会创建和删除列表吗,本文给大家介绍... 目录一、前言二、列表的创建方式1. 字面量语法(最常用)2. 使用list()构造器3. 列表推导式

C++ move 的作用详解及陷阱最佳实践

《C++move的作用详解及陷阱最佳实践》文章详细介绍了C++中的`std::move`函数的作用,包括为什么需要它、它的本质、典型使用场景、以及一些常见陷阱和最佳实践,感兴趣的朋友跟随小编一起看... 目录C++ move 的作用详解一、一句话总结二、为什么需要 move?C++98/03 的痛点⚡C++

Go异常处理、泛型和文件操作实例代码

《Go异常处理、泛型和文件操作实例代码》Go语言的异常处理机制与传统的面向对象语言(如Java、C#)所使用的try-catch结构有所不同,它采用了自己独特的设计理念和方法,:本文主要介绍Go异... 目录一:异常处理常见的异常处理向上抛中断程序恢复程序二:泛型泛型函数泛型结构体泛型切片泛型 map三:文

详解C++ 存储二进制数据容器的几种方法

《详解C++存储二进制数据容器的几种方法》本文主要介绍了详解C++存储二进制数据容器,包括std::vector、std::array、std::string、std::bitset和std::ve... 目录1.std::vector<uint8_t>(最常用)特点:适用场景:示例:2.std::arra

C++构造函数中explicit详解

《C++构造函数中explicit详解》explicit关键字用于修饰单参数构造函数或可以看作单参数的构造函数,阻止编译器进行隐式类型转换或拷贝初始化,本文就来介绍explicit的使用,感兴趣的可以... 目录1. 什么是explicit2. 隐式转换的问题3.explicit的使用示例基本用法多参数构造