STL——栈和队列和优先队列

栈和队列和优先队列

  • 概述
  • std::堆栈
    • 核心函数和操作
    • 成员函数
    • 示例
    • 注意事项
  • std::队列
    • 核心函数和操作
    • 成员函数
    • 示例
    • 注意事项
  • std::优先队列
    • 底层实现原理
    • 效率分析
    • deque双端队列
      • 原理
      • 块结构:
      • 指针管理:
      • 元素访问:
      • 示例代码

概述

学到这里对于容器的基础内容都是大概掌握了的,所以直接讲重点

栈(Stack)

栈是一种后进先出(LIFO, Last In First Out)的数据结构,类比为一个容器,你只能从容器的顶部(栈顶)添加或移除元素,不能在中间或底部进行操作。栈的基本操作包括:

  • 压入(Push):将元素放入栈顶。
  • 弹出(Pop):从栈顶移除元素。
  • 查看栈顶元素(Top):查看但不移除栈顶元素。
  • 判空(Empty):判断栈是否为空。
  • 大小(Size):获取栈中元素的个数。

栈常用于需要“后进先出”操作的场景,比如函数调用的执行过程(存储局部变量和调用信息)、表达式求值(处理运算符优先级)、浏览器的返回按钮(记录访问历史)等。

队列(Queue)

队列是一种先进先出(FIFO, First In First Out)的数据结构,类比为排队,你只能从队列的一端(队尾)添加元素,从另一端(队首)移除元素。队列的基本操作包括:

  • 入队(Enqueue):将元素添加到队列的末尾。
  • 出队(Dequeue):从队列的头部移除元素。
  • 查看队首元素(Front):查看但不移除队首元素。
  • 查看队尾元素(Back):查看但不移除队尾元素。
  • 判空(Empty):判断队列是否为空。
  • 大小(Size):获取队列中元素的个数。

队列常用于需要“先进先出”操作的场景,比如任务调度(先到先服务)、缓冲管理(网络数据包传输)、打印队列(打印机任务管理)等。

优先队列(Priority Queue)

优先队列是一种根据元素的优先级来确定出队顺序的队列,而不是严格的先进先出。具体来说,每次出队操作都会返回具有最高(或最低)优先级的元素。优先队列的特点是:

元素之间有优先级顺序,高优先级的元素先出队。

通常使用堆(Heap)这种数据结构来实现,因为堆能够高效地支持插入和删除操作,并保持元素的部分有序性。

基本操作包括插入元素、获取顶部元素(具有最高优先级的元素)、删除顶部元素等。

优先队列常用于需要动态维护一组数据中的优先级顺序的场景,比如任务调度(优先级高的任务优先执行)、事件模拟(按照发生时间的优先级处理事件)等。

在这里插入图片描述

std::堆栈

template <class T, class Container = deque > class stack;

后进先出堆栈

堆栈是一种容器适配器,专门设计用于在后进先出环境(后进先出)下运行,其中元素仅从容器的一端插入和提取。

堆栈S 作为容器适配器实现,这些适配器是使用特定容器类的封装对象作为其底层容器的类,提供一组特定的成员函数来访问其元素。元素从特定容器的“背面”推出/弹出,该容器称为堆栈的顶部。

底层容器可以是任何标准容器类模板,也可以是其他一些专门设计的容器类。容器应支持以下操作:

empty
size
back
push_back
pop_back

标准容器类,并满足这些要求。默认情况下,如果未为特定类实例化指定容器类,则使用标准容器。

核心函数和操作

构造函数和析构函数

  • stack:创建一个空栈,其中 T 是存储的数据类型。
  • stack(const stack& other):复制构造函数,用于复制另一个栈的内容。

成员函数

  • push(const T& value):将元素压入栈顶。
  • pop():从栈顶移除元素,不返回任何值。
  • top():返回栈顶元素的引用,但不将其从栈中移除。
  • empty():检查栈是否为空,返回 true 或 false。
  • size():返回栈中元素的数量。

示例

#include <iostream>
#include <stack>int main() {std::stack<int> s;// Pushing elements onto the stacks.push(10);s.push(20);s.push(30);// Checking if stack is emptyif (!s.empty()) {std::cout << "Stack size: " << s.size() << std::endl;// Accessing top elementstd::cout << "Top element: " << s.top() << std::endl;// Popping elementss.pop();std::cout << "Popped top element." << std::endl;// Accessing top element after poppingstd::cout << "Top element now: " << s.top() << std::endl;}return 0;
}

注意事项

访问栈顶元素:使用 top() 函数之前,需要确保栈非空,否则会导致未定义行为。

移除栈顶元素:使用 pop() 函数会移除栈顶元素,但不返回该元素的值。

复制栈:使用复制构造函数和赋值操作符时,会复制整个栈的内容,包括元素顺序。

空栈访问:尝试在空栈上调用 top() 或 pop() 会导致运行时错误(未定义行为),因此在使用这些操作前应当检查栈是否为空。

std::队列

template <class T, class Container = deque > class queue;

FIFO队列

队列S 是一种容器适配器,专门设计用于在 FIFO 上下文(先进先出)中运行,其中元素插入容器的一端并从另一端提取。

队列 S 作为容器适配器实现,这些适配器是使用特定容器类的封装对象作为其底层容器的类,提供一组特定的成员函数来访问其元素。元素被推入特定容器的“后部”,并从其“前部”弹出。

底层容器可以是标准容器类模板之一,也可以是其他一些专门设计的容器类。此基础容器应至少支持以下操作:
empty
size
front
back
push_back
pop_front

标准容器类别,并满足这些要求。默认情况下,如果未为特定类实例化指定容器类,则使用标准容器。

核心函数和操作

构造函数和析构函数

  • queue:创建一个空队列,其中 T 是存储的数据类型。
  • queue(const queue& other):复制构造函数,用于复制另一个队列的内容。

成员函数

  • push(const T& value):将元素插入队列的末尾。
  • pop():从队列的开头移除元素,不返回任何值。
  • front():返回队列的第一个元素的引用,但不将其从队列中移除。
  • back():返回队列的最后一个元素的引用,但不将其从队列中移除。
  • empty():检查队列是否为空,返回 true 或 false。
  • size():返回队列中元素的数量。

示例

#include <iostream>
#include <queue>int main() {std::queue<int> q;// Pushing elements into the queueq.push(10);q.push(20);q.push(30);// Checking if queue is emptyif (!q.empty()) {std::cout << "Queue size: " << q.size() << std::endl;// Accessing front and back elementsstd::cout << "Front element: " << q.front() << std::endl;std::cout << "Back element: " << q.back() << std::endl;// Popping elementsq.pop();std::cout << "Popped front element." << std::endl;// Accessing front element after poppingstd::cout << "Front element now: " << q.front() << std::endl;}return 0;
}

注意事项

访问队列元素:使用 front() 和 back() 函数之前,需要确保队列非空,否则会导致未定义行为。

移除队列元素:使用 pop() 函数会移除队列的第一个元素,但不返回该元素的值。

复制队列:使用复制构造函数和赋值操作符时,会复制整个队列的内容,包括元素顺序。

空队列访问:尝试在空队列上调用 front()、back() 或 pop() 会导致运行时错误(未定义行为),因此在使用这些操作前应当检查队列是否为空。

std::优先队列

底层实现原理

在实现优先队列时,通常使用以下两种主要数据结构:

基于堆(Heap)的实现

堆是一种特殊的二叉树,通常实现为数组。

最大堆(Max Heap):父节点的值总是大于或等于任何一个子节点的值。

最小堆(Min Heap):父节点的值总是小于或等于任何一个子节点的值。

在最大堆中,根节点是优先级最高的元素;在最小堆中,根节点是优先级最低的元素。

平衡二叉搜索树的实现

使用平衡二叉搜索树(如红黑树)来维护有序序列,以支持快速的插入、删除和查找操作。

这种实现保证了元素能够按照优先级有序地存储和访问。

效率分析

插入操作

基于堆的优先队列中,插入操作的时间复杂度为 O(log n),其中 n 是当前队列中元素的数量。这是因为插入新元素后,需要调整堆以恢复堆的性质。
平衡二叉搜索树实现的优先队列中,插入操作的时间复杂度为 O(log n),其中 n 是当前队列中元素的数量。这是因为需要保持树的平衡特性。

删除操作

删除操作是指移除优先队列中优先级最高的元素。在基于堆的实现中,删除操作的时间复杂度为 O(log n),因为移除根节点后,需要进行堆的重排。
平衡二叉搜索树实现的优先队列中,删除操作的时间复杂度为 O(log n),因为需要保持树的平衡。

获取最高优先级元素

获取优先队列中优先级最高的元素(即队头元素)的时间复杂度为 O(1)。这是因为在堆中,根节点始终是最大或最小值;在平衡二叉搜索树中,最小或最大元素也可以通过一些常数时间的操作得到。

deque双端队列

deque(双端队列)是C++标准模板库(STL)中的一种容器,它结合了向量(vector)和链表(list)的优点,支持在两端高效地进行元素的插入和删除操作。下面是关于 deque 容器的原理和效率的详细解释:

原理

deque 的名称来源于 “double-ended queue”,即双端队列。它通过一系列的块(chunks)来存储元素,每个块内部通常是一个固定大小的数组,这个数组可以容纳多个元素。deque 的关键设计包括:

块结构:

deque 内部通常由多个块组成,每个块是一个固定大小的数组(或者链表节点)。
每个块存储元素,并且每个块具有前驱和后继块的指针,形成了一个双向链表结构。

指针管理:

deque 维护了指向第一个块和最后一个块的指针,使得在队列的头部和尾部进行快速插入和删除操作成为可能。

对于头部和尾部的插入和删除操作,通过调整指针和在必要时创建或销毁块来维护块的结构。

元素访问:

deque 允许使用迭代器访问元素,迭代器支持双向遍历,并且支持随机访问(通过双向迭代器和块索引的组合实现)。
内存分配:

deque 内部使用动态内存分配来管理块的创建和销毁。这种方式避免了频繁的内存重分配,提高了插入和删除操作的效率。
效率
deque 提供了以下操作的平均时间复杂度:

头部插入和删除(push_front, pop_front):O(1)
尾部插入和删除(push_back, pop_back):O(1)
随机访问(通过迭代器或下标访问):O(1)
相比于 vector 和 list,deque 的主要优势在于

头部操作的高效性:与 vector 相比,deque 的头部插入和删除操作更为高效,因为 vector 需要移动大量元素。
尾部操作的高效性:与 list 相比,deque 在尾部插入和删除操作上的效率更高,因为 list 的每个元素都需要一个额外的指针。

在这里插入图片描述

示例代码

#include <deque>
#include <iostream>int main() {std::deque<int> dq;dq.push_back(1);  // 尾部插入dq.push_front(2); // 头部插入std::cout << dq.front() << " " << dq.back() << std::endl; // 输出:2 1dq.pop_back();    // 尾部删除dq.pop_front();   // 头部删除return 0;
}

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

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

相关文章

企业源代码加密软件|6款好用的源代码加密软件推荐

在软件开发领域&#xff0c;源代码作为企业最核心的资产之一&#xff0c;其安全性直接关系到企业的技术竞争力和商业机密保护。因此&#xff0c;选择一款高效、可靠的源代码加密软件对于企业来说至关重要。以下是企业源代码加密软件的六款推荐&#xff0c;每款软件均具备其独特…

【Android】系统架构、四大组件、结构目录

文章目录 Android系统架构Android四大组件ActivityServiceBroadcast ReceiverContent Provider 两大视图主要结构目录 Android系统架构 linux内核层 为设备的各种硬件提供了底层的驱动&#xff0c;如显示驱动等 系统运行库层 通过C/C库来为android提供主要的特性支持。如SQLit…

普元Devops学习笔记-devops对接jenkins提示crumb不可用问题

前言 普元devops需要对接jenkins&#xff0c;对接jenkins后&#xff0c;devops会调用jenkins的提供的API。 问题 新版本的jenkins提供跨域保护&#xff0c;即大名鼎鼎的CSRF问题。 因此&#xff0c;普元devops调用jenkins的时候&#xff0c;会出现跨域问题。 后台报错信息如…

【kubernetes】kubeadm部署k8s集群

1、环境准备 master01: 192.168.10.25master02: 192.168.10.26master03: 192.168.10.27node01: 192.168.10.28node02: 192.168.10.29负载均衡器1&#xff1a;192.168.10.30负载均衡器2&#xff1a;192.168.10.31 //所有节点&#xff0c;关闭防火墙规则&#xff0c;关闭selinu…

大型语言模型入门

大型语言模型ChatGPT 快速、全面了解大型语言模型。学习李宏毅课程笔记。 ChatGPT 目前由OpenAI公司发明的非常火的人工智能AI应用ChatGPT&#xff0c;到底是什么原理呢&#xff1f; G&#xff1a;Generative(生成) P&#xff1a;Pre-trained(预训练) T&#xff1a;Transform…

2024年7月25日(Git gitlab以及分支管理 )

分布式版本控制系统 一、Git概述 Git 是一种分布式版本控制系统,用于跟踪和管理代码的变更。它是由Linus Torvalds创建的,最 初被设计用于Linux内核的开发。Git允许开发人员跟踪和管理代码的版本,并且可以在不同的开 发人员之间进行协作。 Github 用的就是Git系统来管理它们的…

【Unity编辑器拓展】GraphView自定义可视化节点

1、创建节点区域脚本 其中的new class UxmlFactory&#xff0c;可以让该元素显示在UI Builder中&#xff0c;我们就可以在Library-Project中看到我们新建的这两个UI元素&#xff0c;就可以拖入我们的UI窗口编辑了 public class NodeTreeViewer : GraphView {public new class…

一文了解一下 MindSpeed,MindSpeed 是专为华为昇腾设备设计的大模型分布式加速套件。

https://gitee.com/ascend/MindSpeed Gitee Ascend/MindSpeed 项目&#xff0c;MindSpeed 是针对华为昇腾设备的大模型加速库。 MindSpeed 是专为华为昇腾设备设计的大模型加速库&#xff0c;旨在解决用户在大模型训练过程中遇到的显存资源不足等挑战。该库借鉴了 Megatron、D…

福建聚鼎:现在的装饰画还赚钱不

在轻风拂面的清晨&#xff0c;或在星光璀璨的夜晚&#xff0c;人们常常沉浸于对艺术的思考。装饰画作为艺术的一种表现形式&#xff0c;既丰富了人们的精神世界&#xff0c;又装点了生活的每一个角落。但在这个快速变化的时代&#xff0c;一个引人深思的问题浮出水面&#xff1…

前端-如何通过docker打包Vue服务成镜像并在本地运行(本地可以通过http://localhost:8080/访问前端服务)

1、下载安装docker&#xff0c;最好在vs code里安装docker的插件。 下载链接&#xff1a;https://www.docker.com/products/docker-desktop &#x1f389; Docker 简介和安装 - Docker 快速入门 - 易文档 (easydoc.net) 2、准备配置文件-dockerfile文件和nginx.conf文件 do…

postman查询单条数据Get方法,无任何输出,idea后端也没有任何数据和提示的解决方法

问题描述&#xff1a; 正常使用postman测试&#xff0c;输入内容没有错误&#xff0c;但是却没有任何消息 后端也是&#xff0c;没有任何消息&#xff1a; 解决方法&#xff1a; 问题的原因主要是因为postman&#xff1a; 我们只需要新建一个页面&#xff0c;把刚才的查询语…

《C语言程序设计 第4版》笔记和代码 第十二章 数据体和数据结构基础

12.1从基本数据类型到抽象数据类型 1 所有的程序设计语言都不能将所有复杂数据对象作为其基本数据类型&#xff0c;因此需要允许用户自定义数据类型&#xff0c;在C语言中&#xff0c;就存在构造数据类型&#xff08;复合数据类型&#xff09;。 2 结构体是构造数据类型的一种…

记录|如何统一管理多个同一个对象?

目录 前言一、对象就用对象数组管理更新时间 前言 自己的感想 一开始&#xff0c;自己没弄懂C# winform中的testBox是什么&#xff0c;导致创建多个testBox的时候要用很笨的方法来进行管理。 就是下面这种&#xff1a;用数组一个一个掉用里面的单独属性。 string[] str new …

芋道以开源之名行下作之事 恬不知耻 标榜自己开源 公开源码+sql 不用再加入知识星球

资源 链接: https://pan.baidu.com/s/1TeuxbAUfLQ5_BqMBF1kniQ?pwdcqud 提 取码: cqud 依次为后端、补充版的sql、前端 此文档内安装部署等一应俱全

反序列化靶机serial漏洞复现 超详细教程

环境搭建 漏洞环境&#xff1a;https://www.vulnhub.com/entry/serial-1,349/ 下载后使用Vmware打开 创建新的虚拟机&#xff1a; 选择客户机版本为Ubuntu 64位&#xff1a; 一直下一步&#xff0c;知道选择使用现有磁盘&#xff1a; 选择下载的vmdk磁盘文件&#xff1a; 开机…

24年电赛——自动行驶小车(H题)完赛感受

前言&#xff1a; 笔者大二&#xff0c;也算是第一次正式的打电赛省赛&#xff08;大一电赛的时候还没接触32&#xff0c;校赛的时候就被刷下去了。。。&#xff09;。经过一年的学习&#xff0c;三天两夜的校赛、两天一夜的七校联赛终于是挺到了省赛。比赛过程中真的是有太多感…

Git、Gitlab以及分支管理

分布式版本控制系统 一、Git概述 Git是一种分布式版本控制系统&#xff0c;用于跟踪和管理代码的变更。它由Linus torvalds创建的&#xff0c;最初被设计用于Linux内核的开发。Git 允许开发人员跟踪和管理代码的版本&#xff0c;并且可以在不同的开发人员之间进行协作。 Githu…

浏览器用户文件夹详解 - WebData(八)

1.WebData简介 1.1 什么是WebData文件&#xff1f; WebData文件是Chromium浏览器中用于存储用户表单数据、自动填充信息和支付信息的一个重要文件。每当用户在浏览器中填写表单或保存支付信息时&#xff0c;这些数据都会被记录在WebData文件中。通过这些记录&#xff0c;浏览…

【C语言】C语言期末突击/考研--指针(一篇就够)

目录 一、指针的本质&#xff08;间接访问原理&#xff09; 1.1.指针的定义 1.2.取地址操作符与取值操作符&#xff0c;指针本质 二、指针的传递使用场景 2.1.什么是指针的传递 2.2.指针的传递使用场景 三、指针的偏移使用场景 3.1.指针的偏移 3.2.指针与一维数组 四…

【多线程】阻塞队列

&#x1f3c0;&#x1f3c0;&#x1f3c0;来都来了&#xff0c;不妨点个关注&#xff01; &#x1f3a7;&#x1f3a7;&#x1f3a7;博客主页&#xff1a;欢迎各位大佬! 文章目录 1. 阻塞队列是什么2. 简单使用阻塞队列3. 阻塞队列的应用场景——生产者消费者模型3.1 生产者消…