栈和队列的模拟实现

栈和队列的模拟实现

  • 容器适配器
  • priority_queue(优先级队列)
    • priority_queue的使用
    • priority_queue的模拟实现:
  • 仿函数
    • 什么叫仿函数?
    • 需要自己实现仿函数的情况:
  • 栈的模拟实现
  • 队列的模拟实现
  • deque(vector和list的缝合怪)
    • 为什么选择deque作为stack和queue的底层默认容器?
    • deque的优缺点
  • vector和list的优缺点

容器适配器

容器适配器(Container Adapter) 是一种基于现有容器类(如 vector、deque、list 等)构建的 包装器(Wrapper)。

1.容器适配器本身不直接管理数据存储,而是依赖底层容器(称为 底层容器 或 基础容器)实现存储和访问操作。例如:

stack 默认基于 deque 实现。
queue 默认基于 deque 实现。
priority_queue 默认基于 vector 实现。

2.适配器会屏蔽底层容器的部分接口,仅暴露特定操作所需的接口。

栈(stack) 只允许在栈顶进行插入(push)和删除(pop)操作,屏蔽了随机访问等功能。
队列(queue) 只允许在队尾插入(push)、队头删除(pop),屏蔽了中间元素的操作。

3.底层容器可定制。

#include <stack>
#include <vector>
#include <list>// 使用 vector 作为底层容器
std::stack<int, std::vector<int>> stack1;// 使用 list 作为底层容器
std::stack<int, std::list<int>> stack2;

priority_queue(优先级队列)

priority_queue的使用

int main()
{priority_queue<int> pq;//默认是大的优先级高(大堆)//变小堆//priority_queue<int,vector<int>,greater<int>> pq;pq.push(4);pq.push(1);pq.push(5);pq.push(7);pq.push(9);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}cout << endl;return 0;
}

大堆调试:
在这里插入图片描述
小堆调试:
在这里插入图片描述

priority_queue的模拟实现:

#include<vector>template<class T>
class Less
{
public:bool operator()(const T& x, const T& y){return x < y;}
};template<class T>
class Greater
{
public:bool operator()(const T& x, const T& y){return x > y;}
};namespace bit
{// 默认是大堆template<class T, class Container = vector<T>, class Compare = Less<T>>class priority_queue{public:void AdjustUp(int child){Compare com;int parent = (child - 1) / 2;while (child > 0){//if (_con[parent] < _con[child])if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}void push(const T& x){_con.push_back(x);AdjustUp(_con.size() - 1);}void AdjustDown(int parent){// 先假设左孩子小size_t child = parent * 2 + 1;Compare com;while (child < _con.size())  // child >= n说明孩子不存在,调整到叶子了{// 找出小的那个孩子//if (child + 1 < _con.size() && _con[child] < _con[child + 1])if (child + 1 < _con.size() && com(_con[child], _con[child + 1])){++child;}//if (_con[parent] < _con[child])if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);}const T& top(){return _con[0];}size_t size() const{return _con.size();}bool empty() const{return _con.empty();}private:Container _con;};
}

仿函数

什么叫仿函数?

仿函数:本质是一个类,这个类重载operator(),他的对象可以像函数一样使用

template<class T>
class Less
{
public:bool operator()(const T& x, const T& y){return x < y;}
};template<class T>
class Greater
{
public:bool operator()(const T& x, const T& y){return x > y;}
};// < 升序
// > 降序
template<class Compare>
void BubbleSort(int* a, int n, Compare com)
{for (int j = 0; j < n; j++){// 单趟int flag = 0;for (int i = 1; i < n - j; i++){//if (a[i] < a[i - 1])if (com(a[i], a[i - 1])){swap(a[i - 1], a[i]);flag = 1;}}if (flag == 0){break;}}
}int main()
{Less<int> LessFunc;Greater<int> GreaterFunc;// 函数对象(仿函数)本质是一个对象cout << LessFunc(1, 2) << endl;cout << LessFunc.operator()(1, 2) << endl;int a[] = { 9,1,2,5,7,4,6,3 };BubbleSort(a, 8, LessFunc);BubbleSort(a, 8, GreaterFunc);BubbleSort(a, 8, Less<int>());BubbleSort(a, 8, Greater<int>());return 0;
}

需要自己实现仿函数的情况:

1.类类型不支持比较大小。
2.支持比较大小,但是比较的逻辑不是你想要的。

class Date
{friend ostream& operator<<(ostream& _cout, const Date& d);
public:Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}bool operator<(const Date& d)const{return (_year < d._year) ||(_year == d._year && _month < d._month) ||(_year == d._year && _month == d._month && _day < d._day);}bool operator>(const Date& d)const{return (_year > d._year) ||(_year == d._year && _month > d._month) ||(_year == d._year && _month == d._month && _day > d._day);}
private:int _year;int _month;int _day;
};ostream& operator<<(ostream& _cout, const Date& d)
{_cout << d._year << "-" << d._month << "-" << d._day;return _cout;
}class DateLess
{
public:bool operator()(Date* p1, Date* p2){return *p1 < *p2;}
};
//测试
priority_queue<Date*, vector<Date*>, DateLess> q2;priority_queue<Date*> q2;q2.push(new Date(2018, 10, 29));q2.push(new Date(2018, 10, 28));q2.push(new Date(2018, 10, 30));cout << *q2.top() << endl;q2.pop();cout << *q2.top() << endl;q2.pop();cout << *q2.top() << endl;q2.pop();

栈的模拟实现

#include<deque>namespace bit
{// Container适配转换出stacktemplate<class T, class Container = deque<T>>//deque:vector和list的缝合怪class stack{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_back();}const T& top() const{return _con.back();}size_t size() const{return _con.size();}bool empty() const{return _con.empty();}private:Container _con;};}

队列的模拟实现

#include<deque>namespace bit
{// Container适配转换出queuetemplate<class T, class Container = deque<T>>class queue{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_front();}const T& front() const{return _con.front();}const T& back() const{return _con.back();}size_t size() const{return _con.size();}bool empty() const{return _con.empty();}private:Container _con;};
}

deque(vector和list的缝合怪)

为什么选择deque作为stack和queue的底层默认容器?

stack是一种后进先出的特殊线性数据结构,因此只要具有push_back()和pop_back()操作的线性结构,都可以作为stack的底层容器,比如vector和list都可以;queue是先进先出的特殊线性数据结构,只要具有push_back和pop_front操作的线性结构,都可以作为queue的底层容器,比如list。但是STL中对stack和queue默认选择deque作为其底层容器,主要是因为:

  1. stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作。
  2. 在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的元素增长时,deque不仅效率高,而且内存使用率高。结合了deque的优点,而完美的避开了其缺陷。

deque的优缺点

在这里插入图片描述

vector和list的优缺点

在这里插入图片描述

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

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

相关文章

idea本地debug断点小技巧

idea本地debug断点小技巧 简单的设置断点条件 断点后&#xff0c;右键这个断点&#xff0c;可以在 condition 中填写能得出布尔的表达式 a 1 你如果写如下&#xff0c;表示先给他赋值&#xff0c;然后断住 a 2; true 断点后设置某个变量的值 在 debug 区域可以设置变量…

Oracle中如何解决FREE BUFFER WAITS

基于性能上的考虑&#xff0c;服务器进程在扫描LRU主列的同时&#xff0c;会将脏块移至LRU-W列&#xff0c;如果发现没有足够可用&#xff08;可替换&#xff09;的BUFFER CACHE&#xff0c;进程并不会无止尽地扫描整条LRU主列&#xff0c;而是在扫描到某个阀值&#xff08;该阀…

Git命令使用全攻略:从创建分支到合并的完整流程

Git命令使用全攻略&#xff1a;从创建分支到合并的完整流程 引言一、初始化项目与基础配置1.1 克隆远程仓库1.2 查看当前分支状态 二、创建与管理分支2.1 从main分支创建新功能分支2.2 查看分支列表2.3 提交代码到新分支2.4 推送分支到GitHub 三、版本发布与标签管理3.1 创建轻…

MATLAB跳动的爱心

520&#xff0c;一个会动的心~~~ function particleHeart2 % author : slandarer% 所需匿名函数 col1Func(n) repmat([255,158,196]./255,[n,1])repmat([-39,-81,-56]./255,[n,1]).*rand([n,1]); col2Func(n) repmat([118,156,216]./255,[n,1])repmat([137,99,39].*.1./255,[n,…

Go的单测gomock及覆盖率命令

安装gomock&#xff1a; go get github.com/golang/mock/gomockgo get github.com/golang/mock/mockgen 使用 mockgen 生成 mock 代码: 参考 mockgen -sourceservice/user.go -destinationservice /mocks/mock_user_service.go -packagemocks go test -coverprofilecoverage.ou…

vue添加loading后修复页面渲染问题

问题&#xff1a;想要通过选择流程&#xff08;1&#xff09;后加载出角色信息&#xff08;2&#xff09; 选择后无法展示经过排查&#xff0c;再调用接口给角色数组赋值后&#xff0c;页面在接口调用完之前就已经渲染完成。接口是采用的异步加载解决&#xff1a;loadingRoles…

Python入门手册:Python简介,什么是Python

在当今数字化时代&#xff0c;编程语言犹如一把把神奇的钥匙&#xff0c;能够开启通往技术世界的大门。而Python&#xff0c;无疑是其中最闪耀的一颗明星。今天&#xff0c;就让我们一起走进Python的世界&#xff0c;从它的起源、应用领域以及优缺点三个方面&#xff0c;来全面…

用PyTorch在超大规模下训练深度学习模型:并行策略全解析

我猜咱们每个人肯定都累坏了&#xff0c;天天追着 LLM 研究社区跑&#xff0c;感觉每天都冒出个新的最牛模型&#xff0c;把之前的基准都给打破了呢。要是你好奇为啥创新速度能这么快&#xff0c;那主要就是研究人员能够在超大规模下训练和验证模型啦&#xff0c;这全靠并行计算…

提示工程(Prompt Engineering)应用技巧

Prompt&#xff08;提示&#xff09;就是用户与大模型交互输入的代称。即我们给大模型的输入称为 Prompt&#xff0c;而大模型返回的输出一般称为 Completion。 Prompt 需要清晰明确地表达需求&#xff0c;提供充足上下文&#xff0c;使语言模型能够准确理解我们的意图。更长、…

[原创](现代Delphi 12指南):[macOS 64bit App开发]: 如何获取目录大小?

[作者] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共24年] 职业生涯: 22年 开发语言: C/C++、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 开发工具: Visual Studio、Delphi、XCode、…

Unity入门学习(四)3D数学(4)之四元数Quaternion

目录 一、什么是四元数 二、和欧拉角的关联以及为什么会出现四元数 三、四元数的基本组成 Unity中的表示&#xff1a; 四、四元数Quaternion这个类中具有的属性和方法 常用属性 核心方法 五、四元数之间的计算 1. 叉乘&#xff08;组合旋转&#xff09; 2. 点积&#…

活体检测接口全面评测:2025年活体检测选择指南

一、活体检测&#xff1a;数字化时代的身份验证基石 活体检测是一种通过分析人体生物特征动态变化来验证身份真实性的技术&#xff0c;其核心在于区分真实人体与伪造样本&#xff08;如照片、视频、3D 面具等&#xff09;。技术原理主要基于以下维度&#xff1a; 多模态数据采…

物联网工程毕业设计课题实践指南

1. 智能家居控制系统 1.1 基于ZigBee的智能家居控制 实践过程 硬件选型主控:CC2530/CC2531传感器:温湿度、光照、人体红外执行器:继电器、电机、LED灯系统架构 A[传感器层] --> B[ZigBee网络] B --> C[网关] C --> D[云平台] D --> E[手机APP] 开…

电网中窃电分析:概念、算法与应用

一、引言 在现代电力系统中&#xff0c;窃电行为是一个严重影响电网经济运行和供电秩序的问题。窃电不仅导致供电企业的经济损失&#xff0c;破坏了电力市场的公平性&#xff0c;还可能对电网的安全稳定运行构成威胁&#xff0c;甚至引发安全事故。随着科技的不断进步&#xff…

一洽小程序接入说明

接入说明 文档以微信小程序作为示例介绍&#xff0c;其他小程序接入操作与此类似 1、添加校验文件 开发者使用微信小程序提供的 webview 组件可以实现打开一洽的H5对话 小程序的“域名配置”中添加一洽的对话域名地址&#xff0c;需要获取校验文件提供给一洽放在域名根目录下…

【数据结构 -- AVL树】用golang实现AVL树

目录 引言定义旋转方式LL型RR型LR型RL型 实现结构获取结点高度平衡因子更新高度左旋右旋插入结点中序遍历 引言 AVL树&#xff0c;基于二叉搜索树通过平衡得到 前面我们知道&#xff0c;通过&#x1f517;二叉搜索树可以便捷快速地查找到数据&#xff0c;但是当序列有序时&am…

PyTorch图像识别模型和图像分割模型体验

文章目录 仓库地址练习&#xff1a;图像自动识别模型数据集说明模型训练和保存导入数据集搭建神经网络训练和保存实现 模型测试测试代码测试结果 练习&#xff1a;图像自动分割模型模型训练和保存加载数据集搭建神经网络训练和保存 模型测试测试代码测试效果 仓库地址 图像识别…

威纶通触摸屏IP地址设定步骤及程序下载指南

在使用威纶通触摸屏时&#xff0c;正确设定IP地址以及完成程序下载是确保其正常运行和实现功能的关键步骤。本文将详细介绍威纶通触摸屏IP地址设定步骤及程序下载的方法。 一、IP地址设定步骤 &#xff08;一&#xff09;前期准备 确保威纶通触摸屏已经通电并启动&#xff0…

一文读懂|大模型智能体互操作协议:MCP/ACP/A2A/ANP

导读 随着推理大模型的出现&#xff08;deepseek&#xff0c;Qwen3等&#xff09;&#xff0c;进一步地推进了大模型的智能体系统发展。然而&#xff0c;如何使智能体更好的调用外部工具&#xff0c;智能体与智能体之间如何有机地协作&#xff0c;仍然没有一个完美的答案。这篇…

前端下载ZIP包方法总结

在前端实现下载 ZIP 包到本地&#xff0c;通常有以下几种方法&#xff0c;具体取决于 ZIP 包的来源&#xff08;静态文件、后端生成、前端动态生成等&#xff09;&#xff1a; 方法 1&#xff1a;直接下载静态文件&#xff08;最简单&#xff09; 如果 ZIP 包是服务器上的静态…