栈和队列的模拟实现

文章目录

  • 一. 回顾栈和队列
  • 二. stack的模拟实现
    • stack.h
    • stack.cpp
  • 三. queue的模拟实现
    • queue.h
    • test.cpp
  • 四. 了解dequeue
    • vector和list都有各自的缺陷
    • deque
  • 总结

一. 回顾栈和队列

回顾一下栈和队列

  • 栈:stack:后进先出
    在这里插入图片描述
    _ 队列:queue:先进先出
    在这里插入图片描述
    设计模式有很多种,借鉴设计模式的参考书:设计模式 - 可复用的面向对象软件元素,得知总共有 23 种设计模式。

设计模式是是前辈们对代码开发经验的总结,是解决特定问题的一系列套路,比如适配器模式,迭代器模式

栈和队列是容器适配器,而不是容器。

  • 迭代器模式:将迭代器封装之后提供统一的访问方式,优点:不暴露底层细节
  • 适配器模式:适配器其实是一种转换,通过已有的东西封装转换出你想要的东西。比如电源适配器(电压电流的转换,家里的电源电压通常是220v,而某个电子产品之许哟啊20v的电压,这个时候就需要用到适配器)

stack的使用

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<iostream>
#include<stack>
#include<queue>
int main()
{
	std::stack<int> st1;
	st1.push(1);
	st1.push(2);
	st1.push(3);
	st1.push(4);
	std::cout <<"在未删除之前st1的元素个数" << st1.size() << std::endl;
	//栈是后进先出,所以现在想打印的话,打印的是栈顶元素
	while (!st1.empty())
	{
		std::cout << st1.top() << " ";
		//只能将栈顶元素删除,才能打印下一个元素
		st1.pop();
	}
	std::cout << std::endl;
	std::cout << "在删除之后st1的元素个数" << st1.size() << std::endl;

	std::stack<int> st2;
	st2.push(8);
	st2.push(7);
	st2.push(6);
	st2.push(5);
	st2.swap(st1);
	std::cout << "st1和st2交换之后,st1的元素" << std::endl;
	while (!st1.empty())
	{
		std::cout << st1.top() << " ";
		//只能将栈顶元素删除,才能打印下一个元素
		st1.pop();
	}
	std::cout << std::endl;

	return 0;
}

在这里插入图片描述

二. stack的模拟实现

stack.h

先在私有部分将类的成员变量写出来,我们需要一个容器。

//Container有可能是vector,也有可能是list
Container _con;

首先要知道stack栈都有什么接口,我们再实现
在这里插入图片描述
需要实现判空,返回栈中元素的个数,栈顶元素,尾插和尾删,交换。

用C++的好处就是可以直接使用容器的接口,我们现在想用vector或list来实现stack(在过程中,可以使用vector和list的接口。

从接口可以看出,无论容器是vector还是list,都可以使用尾插尾删,以及back(获取最后一个元素),empty(判空)。
在这里插入图片描述

  • 所以,模拟实现stack的时候,容器vector和list都可以使用

  • 注意点:使用使用vector,要么展开命名空间using namespace std,要么写std::vector

#pragma once
#include<stdio.h>
#include<iostream>
#include<vector>
#include<list>
namespace hou
{
	template<class T,class Container>
	class stack
	{
	public:
		//向容器里插入数据(这里是实现stack,是尾插尾删)
		void push(const T& x)
		{
			_con.push_back(x);
		}
		void pop()
		{
			_con.pop_back();
		}
		const T& top()
		{
			return _con.back();
		}
		bool empty()
		{
			return _con.empty();
		}
		size_t size()
		{
			return _con.size();
		}
	private:
		Container _con;
	};
}

stack.cpp

#include"stack_queue.h"
int main()
{
	hou::stack<int,std::vector<int>> mystack1;
	mystack1.push(11);
	mystack1.push(12);
	mystack1.pop();
	std::cout<<mystack1.size()<<std::endl;
	return 0;
}

三. queue的模拟实现

队列queue是先进先出,也就是尾插头删

在这里插入图片描述

queue.h

#pragma once
#include<stdio.h>
#include<iostream>
#include<vector>
#include<list>
namespace hou
{
	template<class T,class Container>
	class queue   
	{
	public:
		void push(const T& x)
		{
			_con.push_back(x);
		}
		void pop()
		{
			_con.pop_front();
		}
		const T& front()
		{
			return _con.front();
		}
		const T& back()
		{
			return _con.back();
		}
		bool empty()
		{
			return _con.empty();
		}
		size_t size()
		{
			return _con.size();
		}
	private:
		Container _con;
	};
}

test.cpp

int main()
{
	hou::queue<int, std::list<int>> myqueue1;
	myqueue1.push(1);
	myqueue1.push(2);
	myqueue1.push(3);
	while (!myqueue1.empty())
	{
		std::cout << myqueue1.front() << std::endl;
		myqueue1.pop();
	}
	return 0;
}

四. 了解dequeue

查看stack和queue的文档时发现:Container的缺省值不是vector或list,而是deque,deque是一个双端队列(两端都可以插入删除)

queue:template <class T, class Container = deque<T> > class queue;
list:template <class T, class Container = deque<T> > class stack;

vector和list都有各自的缺陷

vector的空间是连续的,而list是一个一个的结点组成的(空间不是连续的)

在这里插入图片描述

  1. vector的物理地址是连续的,可以使用[]访问元素(vector支持随机访问)。但同时也就导致头插头删非常麻烦,头插有扩容消耗(先查看空间是否足够,再将后面的内容一个一个往后移),头删/中部删的效率低(后面的内容往前移)。

在这里插入图片描述
2. list的物理空间是不连续的,它无法通过[]来访问元素(不支持随机访问)。同时也致使CPU高速缓存命中率低。但是list头插头删很容易,改变链接即可。

deque

deque兼具vector和list之长(既可以随机访问,又可以不那么)
在这里插入图片描述

底层实现:开一个又一个小的数组buffer,再用一个中控数组将这些buffer管理起来(中控数组它的每个元素是指针,是每个buffer的地址),所以每个buffer不用想着下一个buffer是谁,这个由中控数组在管理。

deque并不是真正连续的空间,而是由一段一段的(名字为buffer)的小空间拼接而成,再由中控数组来控制。

在这里插入图片描述

  • 如果中控数组满了呢?那就需要异地扩容,但也不复杂,将地址复制过来就OK。
  • 在deque中,不是将第一个buffer放在最前面,而是将中控数组的前几个位置空出来,为了之后需要头插做准备,如果前面有位置的话,就不用挪动数据了。

deque虽然有queue和list的优点,但也有不足的地方,无法取代它俩。

  1. deque在随机访问的时候,需要知道某个数据在哪个buffer里?又是在这个buffer的第几个元素?(第几个buffer:用数据所在的位置/10。buffer的第几个元素:用数据所在的位置%10)。下标的随机访问有一定的消耗,没有vector的随机访问快。

  2. 若是想在某个buffer里插入数据或删除buffer里的某个数据,怎么做呢?
    (1)挪动这个数据后面的数据--------->效率低
    (2)只挪动当前buffer的数据----------->效率还可以,(删除某个buffer的数据且只挪动当前buffer的元素)但是会导致每个buffer的个数不一样,计算在第几个buffer的第几个元素会更麻烦。所以deque在中间插入删除也有一定的消耗,相比list中间插入删除不够灵活,没有list快栈和队列一般是插入或删除头尾的数据,使用deque当默认适配容器会比较适合!!!

deque不适合遍历。因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某段小空间的边界,导致效率低下。而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑vector和list,deque的应用并不多,而目前能看到的一个应用就是,STL用其作为stack和queue**的底层数据结构

deque作为stack和queue的底层默认容器 :在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的元素增长时,deque不仅效率高,而且内存使用率高

在这里插入图片描述

总结

模拟实现stack:vector和list都可以使用
模拟实现queue:只能使用容器list(队列是先进先出,也就是头删,而vector没有头删这个接口)
实现stack和queue的默认适配容器是deque。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】之【Bug】VMware 虚拟机开机 一直卡在黑屏左上角下划线闪烁界面

解决 参考&#xff1a; 解决Ubuntu20.04 开机黑屏光标闪烁进不去系统 Centos根目录100%解决思路 当前界面 ctrlaltf3-f6 暂时进入终端界面 df -h 查看发现根目录 磁盘空间已满 执行命令 查看当前目录占用内存明细 sudo du -h -x --max-depth1清理无用的大内存文件 或者安装…

【uniapp】离线打包uniapp为apk详细步骤

先看效果 登录页面的图片由于来自于图鸟官网&#xff0c;这里没有显示。 离线打包uniapp为apk 运行环境&#xff1a;华为mate30&#xff0c;已经升级为鸿蒙系统。 参考文档 https://blog.csdn.net/xiaoyao_studio/article/details/144076431 https://juejin.cn/post/739…

【通俗讲解电子电路】——从零开始理解生活中的电路(一)

导言&#xff1a;电子电路为什么重要&#xff1f; ——看不见的“魔法”&#xff0c;如何驱动你的生活&#xff1f; 清晨&#xff0c;当你的手机闹钟响起时&#xff0c;你可能不会想到&#xff0c;是电子电路在精准控制着时间的跳动&#xff1b;当你用微波炉加热早餐时&#…

Octave3D 关卡设计插件

课程参考链接 这位大佬有在视频合集中有详细的讲解&#xff0c;个人体验过&#xff0c;感觉功能很强大 https://www.bilibili.com/video/BV1Kq4y1C72P/?share_sourcecopy_web&vd_source0a41d8122353e3e841ae0a39908c2181 Prefab资源管理 第一步 在场景中创建一个空物体…

通过多线程分别获取高分辨率和低分辨率的H264码流

目录 一.RV1126 VI采集摄像头数据并同时获取高分辨率码流和低分辨率码流流程 ​编辑 1.1初始化VI模块&#xff1a; 1.2初始化RGA模块&#xff1a; 1.3初始化高分辨率VENC编码器、 低分辨率VENC编码器&#xff1a; 1.4 VI绑定高分辨率VENC编码器&#xff0c;VI绑定RGA模块…

【Python 数据结构 1.零基础复习】

目录 一、输入与输出 1.输入 2.格式化输出 二、数字与变量 1.字符串 & 整型 2.字符串 & 整型 & 浮点型 3.变量 练习 2235. 两整数相加 三、运算与操作 1.四则运算 练习 2769. 找出最大的可达成数字 3.取整与取余 练习 2651. 计算列车到站时间 ​编辑 四、真与假 1…

21. 构造二叉树(卡码网)

21. 构造二叉树 find&#xff08;&#xff09;方法 在Python中&#xff0c;str.find(sub[, start[, end]]) 方法用于查找子字符串 sub 在字符串中首次出现的位置&#xff0c;返回其起始索引。如果未找到&#xff0c;返回 -1 class Tree:def __init__(self,valNone,leftNone,r…

RocketMQ定时/延时消息实现机制

RocketMQ 的延迟消息是其核心特性之一&#xff0c;允许消息在指定延迟时间后才被消费者消费。 定时消息生命周期 一、延迟消息的核心机制 RocketMQ&#xff08;5.0之前&#xff09; 不支持任意时间精度的延迟&#xff0c;而是通过预定义的 延迟级别&#xff08;Delay Level&a…

【编程题】7-3 树的同构

7-3 树的同构 1 题目原文2 思路解析3 代码实现4 总结 1 题目原文 题目链接&#xff1a;7-3 树的同构 给定两棵树 T 1 T_1 T1​ 和 T 2 T_2 T2​​。如果 T 1 T_1 T1​ 可以通过若干次左右孩子互换就变成 T 2 T_2 T2​&#xff0c;则我们称两棵树是“同构”的。例如图 1 1 …

WebP2P技术在嵌入式设备中的应用:EasyRTC音视频通话SDK如何实现高效通信?

在数字化时代&#xff0c;实时通信技术&#xff08;RTC&#xff09;与人工智能&#xff08;AI&#xff09;的融合正在重塑各个行业的交互方式。从在线教育到远程医疗&#xff0c;从社交娱乐到企业协作&#xff0c;RTC的应用场景不断拓展。然而&#xff0c;传统的RTC解决方案往往…

【前端】前端设计中的响应式设计详解

文章目录 前言一、响应式设计的定义与作用二、响应式设计的原则三、响应式设计的实现四、响应式设计的最佳实践总结 前言 在当今数字化时代&#xff0c;网站和应用程序需要适应各种设备&#xff0c;从桌面电脑到平板电脑和手机。响应式设计应运而生&#xff0c;成为一种可以适…

【AVRCP】探寻AVRCP控制互操作性:连接、命令与设备交互

AVRCP对于实现设备间的高效音频/视频控制至关重要。而控制互操作性要求作为AVRCP的核心部分&#xff0c;详细规定了设备在连接建立、命令传输等方面的具体操作。确保了不同设备之间能够实现无缝的远程控制。 一、AVCTP连接管理 1.1 AVCTP连接建立 发起者&#xff1a;AVCTP控制…

LLM大型语言模型(一)

1. 什么是 LLM&#xff1f; LLM&#xff08;大型语言模型&#xff09;是一种神经网络&#xff0c;专门用于理解、生成并对人类文本作出响应。这些模型是深度神经网络&#xff0c;通常训练于海量文本数据上&#xff0c;有时甚至覆盖了整个互联网的公开文本。 LLM 中的 “大” …

2025国家护网HVV高频面试题总结来了04(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 一、HVV行动面试题分类 根据面试题的内容&#xff0c;我们将其分为以下几类&#xff1a; 漏洞利用与攻击技术 …

解锁GPM 2.0「卡顿帧堆栈」|代码示例与实战分析

每个游戏开发者都有一个共同的愿望&#xff0c;那就是能够在无需复现玩家反馈的卡顿现象时&#xff0c;快速且准确地定位卡顿的根本原因。为了实现这一目标&#xff0c;UWA GPM 2.0推出了全新功能 - 卡顿帧堆栈&#xff0c;旨在为开发团队提供高效、精准的卡顿分析工具。在这篇…

【人工智能】蓝耘智算平台盛大发布DeepSeek满血版:开创AI推理体验新纪元

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀ 蓝耘智算平台 蓝耘智算平台核心技术与突破元生代推理引擎快速入门&#xff1a;三步调用大模型接口&#xff0c;OpenAI SDK无缝兼容实战用例文…

用Python+Flask打造可视化武侠人物关系图生成器:从零到一的实战全记录

用PythonFlask打造可视化武侠人物关系图生成器&#xff1a;从零到一的实战全记录 一、缘起&#xff1a;一个程序小白的奇妙探索之旅 作为一个接触Python仅13天的编程萌新&#xff0c;我曾以为开发一个完整的应用是遥不可及的事情。但在DeepSeek的帮助下&#xff0c;我竟用短短…

Mac远程桌面软件哪个好用?

远程桌面软件能帮助我们快速的远程控制另一台电脑&#xff0c;从而提供远程帮助&#xff0c;或者进行远程办公。那么&#xff0c;对macOS系统有什么好用的Mac远程桌面软件呢&#xff1f; 远程看看是一款操作简单、界面简洁的远程桌面软件&#xff0c;支持跨平台操作&#xff0…

华为云 | 快速搭建DeepSeek推理系统

DeepSeek&#xff08;深度求索&#xff09;作为一款国产AI大模型&#xff0c;凭借其高性能、低成本和多模态融合能力&#xff0c;在人工智能领域崛起&#xff0c;并在多个行业中展现出广泛的应用潜力。 如上所示&#xff0c;在华为云解决方案实践中&#xff0c;华为云提供的快速…

Unity 内置渲染管线各个Shader的用途和性能分析,以及如何修改Shader(build in shader 源码下载)

文章目录 所有Shader分析路径&#xff1a;Standard路径&#xff1a;Nature/路径&#xff1a;UI/路径&#xff1a;Particles/Particles/Standard SurfaceParticles/Standard Unlit 路径&#xff1a;Unlit/Unlit/TextureUnlit/ColorUnlit/TransparentUnlit/Transparent CutoutUnl…