C++——容器适配器

1. 什么是适配器?

容器适配器是C++标准库中的一种数据结构,它可以将不同类型的容器(如vector、list、deque等)转换为另一种类型的容器。容器适配器提供了一种简单的方式来重新组织和访问数据,同时隐藏了底层容器的实现细节。它们通常用于解决特定的问题或满足特定的需求。

容器适配器有三种常见的类型:栈(stack)、队列(queue)和优先队列

  • 栈(stack):栈是一种后进先出(LIFO)的数据结构,类似于现实生活中的一叠盘子。栈容器适配器提供了push、pop、top等操作,可以方便地在栈顶插入和删除元素。

  • 队列(queue):队列是一种先进先出(FIFO)的数据结构,类似于现实生活中的排队。队列容器适配器提供了push、pop、front等操作,可以方便地在队列尾部插入元素,在队列头部删除元素。

  • 优先队列(priority_queue):优先队列是一种具有优先级的队列,每次取出的元素都是当前队列中优先级最高的元素。优先队列容器适配器提供了push、pop、top等操作,可以方便地插入和删除元素,并且保证每次取出的元素都是最大或最小的。

2. 容器适配器的作用

  1. 改变容器的接口
  2. 增加容器的功能
  3. 限制容器的功能

3. 常见的容器适配

3.1 栈(stack)

3.1.1 概念

栈(stack)是一种常见的容器适配器,它遵循“后进先出”(Last-In-First-Out,LIFO)的原则。栈只允许在末尾进行插入和删除操作,即只能在栈顶进行入栈和出栈操作。

请添加图片描述

3.1.2 基本操作
操作功能
empty判空操作
back获取尾部元素操作
push_back尾部插入元素操作
pop_back尾部删除元素操作

3.1.3 stack的使用

函数说明接口说明
stack()构造空的栈
empty()检测stack是否为空
size()返回stack中元素的个数
top()返回栈元素的引用
push()将元素val压入stack中
pop()将stack中尾部的元素弹出

3.1.4 stack的模拟实现

#include<vector>
#include<iostream>
using namespace std;
namespace bite
{template<class T>class stack{public://构造函数stack() {}//入栈void push(const T& x) {_c.push_back(x); }//出栈void pop() {_c.pop_back(); }//返回栈顶元素T& top() {return _c.back(); }//返回栈顶元素的const版本const T& top()const {return _c.back(); }//大小size_t size()const {return _c.size(); }//判断是否为空bool empty()const {return _c.empty(); }private:std::vector<T> _c;};
}
int main()
{bite::stack<int> mystack;mystack.push(1);mystack.push(2);mystack.push(3);mystack.push(4);mystack.push(5);if (!mystack.empty()){cout << "栈大小:" << mystack.size() << endl;cout << "栈顶元素:" << mystack.top() << endl;}mystack.pop();if (!mystack.empty()){cout << "栈大小:" << mystack.size() << endl;cout << "栈顶元素:" << mystack.top() << endl;}}

3.2 队列(queue)

队列是一种常见的容器适配器,它遵循先进先出(FIFO)的原则。在队列中,元素被添加到末尾,被移除时从头部开始。队列适配器提供了一些常用的操作,如入队(enqueue)和出队(dequeue)。

请添加图片描述

3.2.1 基本操作

操作功能
empty检队列是否为空
size返回队列中有效元素的个数
front返回队头元素的引用
back返回队尾元素的引用
push_back在队列尾部队列
pop_front在队列头部出队列

3.2.2 queue的使用

函数声明接口说明
queue()构造空的队列
empty()检测队列是否为空,是返回true,否则返回false
size()返回队列中有效元素的个数
front()返回头元素的引用
back()返回尾元素的引用
push()将队尾元素val入栈
pop()将头元素出队列

3.2.3 queue的模拟实现

#include<list>
#include<iostream>
using namespace std;
namespace bite
{template<class T>class queue{public://默认构造函数,用于初始化一个新的queue对象queue(){}//入队操作,将元素x添加到队列的末尾void push(const T& x){_c.push_back(x);}//出队操作,移除队列的第一个元素void pop(){_c.pop_front();}//返回队列最后一个元素的引用,允许修改T& back(){return _c.back();}//返回队列最后一个元素的引用,不允许修改const T& back() const{return _c.back();}//返回队列第一个元素的引用,允许修改T& front(){return _c.front();}//返回队列第一个元素的引用,不允许修改const T& front() const{return _c.front();}//返回队列中元素的个数size_t size() const{return _c.size();}//判断队列是否为空bool empty() const{return _c.empty();}private://用于存储队列中的元素list<int> _c;};
}
int main()
{bite::queue<int> myqueue;myqueue.push(1);myqueue.push(2);myqueue.push(3);myqueue.push(4);myqueue.push(5);if (!myqueue.empty()){cout << "队列大小:" << myqueue.size() << endl;cout << "队列第一个元素:" << myqueue.front() << endl;cout << "队列最后一个元素:" << myqueue.back() << endl;}myqueue.pop();if (!myqueue.empty()){cout << "队列大小:" << myqueue.size() << endl;cout << "队列第一个元素:" << myqueue.front() << endl;cout << "队列最后一个元素:" << myqueue.back() << endl;}return 0;
}

3.3 优先队列(priority_queue)

3.3.1 概述

优先队列是一种特殊的队列,其中的元素按照一定的优先级进行排序。在优先队列中,每个元素都有一个与之关联的优先级,具有较高优先级的元素会被优先处理。优先队列通常使用堆数据结构来实现,因为堆能够在插入和删除元素时保持元素的有序性。

3.3.2 基本操作

操作功能
push将一个元素插入到优先级队列中,插入的元素会根据其优先级被放置到合适的位置上
pop移除优先队列中具有最高优先级的元素
top获取优先队列中具有最高优先级的元素,但不会将其从队列中移除
empty检查优先队列是否为空

3.3.3 priority_queue的使用

优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。注意:默认情况下priority_queue是大堆。

函数声明接口说明
priority_queue()/priority_queue(first, last)构造一个空的优先级队列
empty()检测优先级队列是否为空,是返回true,否则返回false
top()返回优先级队列中最大(最小元素),即堆顶元素
push(x)在优先级队列插入元素x
pop()删除优先级队列中最大(最小)元素,即堆顶元素

3.3.4 实现方式

优先队列可以通过堆来实现,常见的堆有大堆和小堆。大堆中,根节点的值最大,每个节点的值都大于或等于其子节点的值;小堆中,根节点的值最小,每个节点的值都小于或等于其子节点的值。优先队列可以根据元素的优先级来构建最大堆或最小堆

3.3.5 基本操作和时间复杂度

操作时间复杂度
插入元素O(long n)
删除元素O(long n)
获取元素首元素O(1)
判断队列是否为空O(1)

3.3.6 priority_queue的模拟实现

#pragma once
#include <iostream>
using namespace std;
#include <vector>
// priority_queue--->堆
namespace bite
{template<class T>struct less{bool operator()(const T& left, const T& right){return left < right;}};template<class T>struct greater{bool operator()(const T& left, const T& right){return left > right;}};template<class T, class Container = std::vector<T>, class Compare = less<T>>class priority_queue{public:// 创造空的优先级队列priority_queue() : c() {}template<class Iterator>priority_queue(Iterator first, Iterator last): c(first, last){// 将c中的元素调整成堆的结构int count = c.size();int root = ((count - 2) >> 1);for (; root >= 0; root--)AdjustDown(root);}void push(const T& data){c.push_back(data);AdjustUP(c.size() - 1);}void pop(){if (empty())return;swap(c.front(), c.back());c.pop_back();AdjustDown(0);}size_t size()const{return c.size();}bool empty()const{return c.empty();}// 堆顶元素不允许修改,因为:堆顶元素修改可以会破坏堆的特性const T& top()const{return c.front();}private:// 向上调整void AdjustUP(int child){int parent = ((child - 1) >> 1);while (child){if (Compare()(c[parent], c[child])){swap(c[child], c[parent]);child = parent;parent = ((child - 1) >> 1);}else{return;}}}// 向下调整void AdjustDown(int parent){size_t child = parent * 2 + 1;while (child < c.size()){// 找以parent为根的较大的孩子if (child + 1 < c.size() && Compare()(c[child], c[child + 1]))child += 1;// 检测双亲是否满足情况if (Compare()(c[parent], c[child])){swap(c[child], c[parent]);parent = child;child = parent * 2 + 1;}elsereturn;}}private:Container c;};
}void TestQueuePriority()
{bite::priority_queue<int> q1;q1.push(5);q1.push(1);q1.push(4);q1.push(2);q1.push(3);q1.push(6);cout << q1.top() << endl;q1.pop();q1.pop();cout << q1.top() << endl;vector<int> v{ 5,1,4,2,3,6 };bite::priority_queue<int, vector<int>, bite::greater<int>> q2(v.begin(), v.end());cout << q2.top() << endl;q2.pop();q2.pop();cout << q2.top() << endl;
}

4. 容器适配器的优点

4.1 封装性

容器适配器隐藏了底层容器的实现细节,只暴露出特定的接口,使得使用者可以方便地操作容器适配器,而不需要了解底层容器的具体实现。

4.2 灵活性

容器适配器可以根据不同的需求选择不同的底层容器来实现功能。例如,可以使用栈来实现适配器,也可以使用队列来实现适配器,这取决于具体的使用场景和要求。

4.3 功能拓展

容器适配器可以根据需要进行扩展,添加新的功能或修改现有功能。由于适配器与底层容器解耦,因此可以独立地对适配器进行修改,而不会影响到其他部分的代码。

4.4 与标准库兼容

容器适配器通常与标准库的容器接口兼容,这意味着可以通过容器适配器来替换标准容器的使用,而不需要修改其他代码。

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

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

相关文章

【数据结构】算法的时间复杂度

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 一.算法时间复杂度定义 二.大O阶渐近表示法 &#x1f38f;大O阶渐近表示法的定义 &#x1f38f;推导大O阶方法 三.常见的时间复杂度 &#x1f4cc;常数阶 &#x…

【C++进阶之路】C++11(中)

一、可变参数模板 1.基本概念 想要了解C语言的可变参数列表的原理可见&#xff1a;可变参数列表 这个跟C语言的可变参数列表有一定的关系,常用的printf与scanf的参数就包含可变参数列表。 那么可变参数模板是什么呢&#xff1f;举个例子便一目了然。 template<class...Arg…

双周赛114(模拟、枚举 + 哈希、DFS)

文章目录 双周赛114[2869. 收集元素的最少操作次数](https://leetcode.cn/problems/minimum-operations-to-collect-elements/)模拟 [2870. 使数组为空的最少操作次数](https://leetcode.cn/problems/minimum-number-of-operations-to-make-array-empty/)哈希 枚举 [2871. 将数…

点击劫持:X-Frame-Options 未配置

前言 X-Frame-Options作为HTTP头的一部分&#xff0c;是一种用于保护网站免受点击劫持攻击的安全措施。网站可以通过设置X-Frame-Options或csp报头来控制网站本身是否可以被嵌套到iframe中。 漏洞描述 Clickjacking&#xff08;点击劫持&#xff09;是一种安全漏洞&#xff…

[天翼杯 2021]esay_eval - RCE(disabled_function绕过||AS_Redis绕过)+反序列化(大小写wakeup绕过)

[天翼杯 2021]esay_eval 1 解题流程1.1 分析1.2 解题1.2.1 一阶段1.2.2 二阶段二、思考总结题目代码: <?php class A{public $code = "";

湖州OLED透明拼接屏技术应用引领现代化旅游观光方式

湖州市位于中国浙江省北部&#xff0c;拥有悠久的历史和丰富的文化遗产。湖州市以其美丽的湖泊和秀丽的自然风光而闻名。 作为中国重要的历史文化名城之一&#xff0c;湖州市有着丰富的文化遗产和历史资源&#xff0c;如古城墙、古建筑和古镇等。 这为OLED透明拼接屏技术的应用…

canvas力导布局

老规矩&#xff0c;先上效果图 <html><head><style>* {margin: 0;padding: 0;}canvas {display: block;width: 100%;height: 100%;background: #000;}</style> </head><body><canvas id"network"></canvas> </…

如何避免 IDEA 每次重启都index

如何避免 IDEA 每次重启都index 在 IntelliJ IDEA 中&#xff0c;可以通过以下几个步骤来避免每次重启时索引&#xff1a; 打开 File -> Settings 菜单。在左侧的菜单栏中选择 “Appearance & Behavior” -> “System Settings” -> “Synchronization”。 在右…

力扣第501题 二叉树的众数 c++ (暴力 加 双指针优化)

题目 501. 二叉搜索树中的众数 简单 相关标签 树 深度优先搜索 二叉搜索树 二叉树 给你一个含重复值的二叉搜索树&#xff08;BST&#xff09;的根节点 root &#xff0c;找出并返回 BST 中的所有 众数&#xff08;即&#xff0c;出现频率最高的元素&#xff09;。 …

【Redis】Set集合相关的命令

目录 命令SADDSMEMBERSSISMEMBERSCARDSPOPSMOVESREMSINTERSINTERSTORESUNIONSUNIONSTORESDIFFSDIFFSTORE 命令 SADD 将⼀个或者多个元素添加到set中。注意&#xff0c;重复的元素⽆法添加到set中。 SADD key member [member ...]SMEMBERS 获取⼀个set中的所有元素&#xff0…

js事件循环详解

事件循环简介 JavaScript的事件循环是一种处理异步事件和回调函数的机制&#xff0c;它是在浏览器或Node.js环境中运行&#xff0c;用于管理任务队列和调用栈&#xff0c;以及在适当的时候执行回调函数。 事件循环的基本原理是&#xff0c;JavaScript引擎在空闲时等待事件的到…

苹果ios开发者ipa文件包内测人数签名真机数量满了应该怎么做?

苹果ios开发者ipa文件包内测人数签名真机数量满了应该怎么做&#xff1f; 有人总是问我开发者的设备满了怎么做才可以让设备增加&#xff1f;或者我要怎么做才能让员工的设备都可以安装&#xff0c;那么首先我们要做到的就是要知道我们的开发者都是拥有多少内测设备&#xff1f…

jupyter notebook如何实现代码提示功能?

jupyter notebook在数据分析中使用非常方便&#xff0c;但是没有代码提示功能&#xff0c;让人感觉有一点点遗憾&#xff1f;如何实现代码提示功能呢&#xff1f;以下实现亲测有效。 本人python版本是3.8. 首先关闭jupyter notebook&#xff0c;安装相关的库。 一、需要提前…

MongoDB——centOS7环境Mongodb权限管理(图解版)

目录 一、MongDB权限概述1.1、MongDB权限概述1.2、MongDB权限列表 二、Mongodb权限管理示例2.1、创建账号2.1.1、创建管理员用户2.1.2、开启认证2.1.3、创建普通账号 一、MongDB权限概述 1.1、MongDB权限概述 mongodb是没有默认管理员账号&#xff0c;所以要先添加管理员账号…

【Python 零基础入门】 函数

【Python 零基础入门】第五课 函数 【Python 零基础入门】第五课 函数函数在生活中的类比函数为什么要使用函数函数的格式无参函数含参函数 参数形参实参 变量作用域局部变量全局变量 递归函数基本的递归斐波那契数列 Lambda 表达式高阶函数map 函数filter 函数reduce 函数结合…

Node历史版本下载及配置npm镜像

https://nodejs.org/en/download/releases 点击对应版本Release,选择合适的包&#xff0c;进行下载安装。 配置国内镜像 npm config set registry https://registry.npmmirror.com/

Practical Memory Leak Detection using Guarded Value-Flow Analysis 论文阅读

本文于 2007 年投稿于 ACM-SIGPLAN 会议1。 概述 指针在代码编写过程中可能出现以下两种问题&#xff1a; 存在一条执行路径&#xff0c;指针未成功释放&#xff08;内存泄漏&#xff09;&#xff0c;如下面代码中注释部分所表明的&#xff1a; int foo() {int *p malloc(4 …

上海亚商投顾:沪指冲高回落 医药、芯片股全天领涨

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 沪指昨日小幅反弹&#xff0c;创业板指盘中涨超1.6%&#xff0c;午后涨幅有所收窄。医药医疗股全线走强&#…

LLM - 旋转位置编码 RoPE 代码详解

目录 一.引言 二.RoPE 理论 1.RoPE 矩阵形式 2.RoPE 图例形式 3.RoPE 实践分析 三.RoPE 代码分析 1.源码获取 2.源码分析 3.rotary_emb 3.1 __init__ 3.2 forward 4.apply_rotary_pos_emb 4.1 rotate_half 4.2 apply_rotary_pos_emb 四.RoPE 代码实现 1.Q/K/V …

飞桨大模型套件:一站式体验,性能极致,生态兼容

在Wave Summit 2023深度学习开发者大会上&#xff0c;来自百度的资深研发工程师贺思俊和王冠中带来的分享主题是&#xff1a;飞桨大模型套件&#xff0c;一站式体验&#xff0c;性能极致&#xff0c;生态兼容。 大语言模型套件PaddleNLP 众所周知PaddleNLP并不是一个全新的模型…