C++ 9 stack_queue:数据结构的核心奥秘

stack

栈(Stack)是一种运算受限的线性表 ,只允许在一端进行插入或删除操作。这一端被称为栈顶 (Top),相对地,另一端称为栈底 (Bottom)。栈的特点是后进先出(Last In First Out,简称LIFO),即最后插入的元素最先被删除。

基本操作

  • push(): 在栈顶添加一个元素。
  • pop(): 移除栈顶元素。
  • top(): 返回栈顶元素的引用,但不移除它。
  • empty(): 检查栈是否为空。
  • size(): 返回栈中元素的数量。
cpp 复制代码
stack<int> st;
st.push(1);
st.push(2);
st.push(3);
st.pop();
cout<<st.top();
st.empty();
cout<<st.size();

模拟实现

cpp 复制代码
#pragma once
namespace Milestone
{
	template<class T,class Container = vector<int>>//给缺省值
	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()
		{
			return _con.empty();
		}
	private:
		Container _con;
	};
}

queue

它允许在一端添加元素(称为队尾),并在另一端移除元素(称为队首)。

队列是一种线性数据结构,它遵循以下规则:

  • 元素只能从队尾添加。
  • 元素只能从队首移除。

基本操作

  • empty(): 检查队列是否为空。
  • size(): 返回队列中的元素数量。
  • front(): 返回队首元素的引用。
  • back(): 返回队尾元素的引用。
  • push(): 在队尾添加一个元素。
  • pop(): 移除队首元素。
cpp 复制代码
queue<int> st;
queue.push(1);
queue.push(2);
queue.push(3);
queue.pop();
cout<<queue.front();
cout<<queue.back();
queue.empty();
cout<<queue.size();

模拟实现

cpp 复制代码
#pragma once

namespace Milestone {
	template<class T,class Container = list<int>>
	class queue {
	public:
		void push(const T& x)
		{
			_con.push(x);
		}
		void pop()
		{
			_con.pop();
		}
		bool empty()
		{
			return _con.empty();
		}
		size_t size()
		{
			return _con.size();
		}
		T& front()const
		{
			return _con.front();
		}
		T& back()const
		{
			return _con.back();
		}
	private:
		Container _con;
	};
}

priority_queue

  1. 优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素
    中最大的。
  2. 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶
    部的元素)。
  3. 优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类,queue
    提供一组特定的成员函数来访问其元素。元素从特定容器的"尾部"弹出,其称为优先队列的
    顶部。
  4. 底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过
    随机访问迭代器访问

基本操作

empty():检测容器是否为空
size():返回容器中有效元素个数
front():返回容器中第一个元素的引用
push_back():在容器尾部插入元素
pop_back():删除容器尾部元素

cpp 复制代码
priority_queue<int> pq;
pq.push(1);
pq.push(2);
pq.empty();
pq.pop();
cout<<pq.top();

模拟实现

cpp 复制代码
#pragma once
namespace Milestone
{
	//默认是大堆
	template<class T,class Container = vector<T>>
	class priority_queue {
	public:
		void adjustup(size_t child)//有隐式this
		{
			size_t parent = (child - 1) / 2;
			while (child > 0)
			{
				if (_con[child] > _con[parent])
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
			}
		}
		void push(const T& x)
		{
			_con.push_back(x);
			adjustup(_con.size() - 1);
		}
		void adjustdown(size_t parent)
		{
			size_t child = parent * 2 + 1;
			while (child < _con.size())
			{
				if (child + 1 < _con.size() && _con[child + 1] > _con[child])
					++child;
				if (_con[child] > _con[parent])
				{
					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()
		{
			return _con.empty();
		}
	private:
		Container _con;
	};
}

容器适配器

什么是容器适配器

适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设
计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口
其中SLT的容器适配器

stack:栈适配器
queue:队列适配器
priority_queue:优先队列适配器
在上述中,stack与queue均选择deque为默认容器

为什么选择deque

**deque(双端队列):是一种双开口的"连续"**空间的数据结构,双开口的含义是:可以在头尾两端
进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与
list比较,空间利用率比较高。

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

vector list deque的优缺点

vector

Vecaor

优点;

1.尾插尾删效率高,支持下标随机访问

2.物理空间连续,所以高速缓存利用率高

缺点:

1.空间需要扩容,扩容有代价(效率和空间)

2.头部和中间插入数据慢

list

优点:

1.按需申请空间,不需要释放空间

2.任意位置插入删除

缺点

1.不支持下标随机访问

deque

优点

1.头插尾插插入效率比vector和list高

2.下标随机访问不错,但相比vector逊

缺点:

1中间插入删除效率低,要挪动数据,为O(N)

相关推荐
fuquxiaoguang1 小时前
深入浅出:使用MDC构建SpringBoot全链路请求追踪系统
java·spring boot·后端·调用链分析
琹箐1 小时前
最大堆和最小堆 实现思路
java·开发语言·算法
__WanG2 小时前
JavaTuples 库分析
java
renhongxia12 小时前
如何基于知识图谱进行故障原因、事故原因推理,需要用到哪些算法
人工智能·深度学习·算法·机器学习·自然语言处理·transformer·知识图谱
坚持就完事了2 小时前
数据结构之树(Java实现)
java·算法
算法备案代理2 小时前
大模型备案与算法备案,企业该如何选择?
人工智能·算法·大模型·算法备案
Monly212 小时前
Java:修改打包配置文件
java·开发语言
roman_日积跬步-终至千里2 小时前
【架构设计与实现】动态数据源切换:核心代码实现手册
java
XiaoFan0122 小时前
免密批量抓取日志并集中输出
java·linux·服务器
顾北122 小时前
MCP服务端开发:图片搜索助力旅游计划
java·spring boot·dubbo