当前位置: 首页 > article >正文

C++STL之stack和queue容器(详细+通俗易懂)

前言:老铁们好,笔者好久没更新STL的容器了,今天,笔者接着之前的STL容器的内容继续更新,所以今天给老铁们分享的是STL里面的栈和队列的容器的知识。

1.栈的定义

老规矩,我们先来看看C++的官网对stack的介绍文档。
在这里插入图片描述
然后我再为老铁们用大白话解释一下文档里面的内容。

1.在数据结构那一门课程中我们就学过,栈具有后进先出的特点,数据只能从栈顶出入,文档中第一点讲的就是这个。

2.栈是作为容器适配器被实现的,什么是容器适配器呢?容器适配器就像一个"转化器"(比如我们的充电线的接口),它能将现有的容器转化为新的,具有特定功能的东西,例如可以将vector,list…转化为stack

3.底层容器可以是任何容器,只需要满足empty,size,back,push_back,pop_back这些操作即可,如果没有我们自己写的容器,那么会使用标准的容器,例如vector,list…

.

2.stack的使用

我会为老铁们逐一演示stack的常用接口是如何使用的。

首先stack使用,需要包头文件

#include <stack>

栈的定义

stack<int> st;//栈里面数据类型是int型

栈的插入数据

stack<int> st;
//插入1 2 3 4
st.push(1);
st.push(2);
st.push(3);
st.push(4);

栈数据的遍历

这里需要注意一下,栈是没有迭代器的,那么我们该如何遍历栈里面的数据呢?

stack<int> st;
//插入1 2 3 4
st.push(1);
st.push(2);
st.push(3);
st.push(4);

while (!st.empty())//判断栈里面的数据不为空
{
	int top = st.top();//取栈顶的数据
	st.pop();//删除该数据,让栈顶的数据进行迭代
	cout << top << endl;
}

代码的预期结果应该是4 3 2 1,那么我们来看看结果吧
在这里插入图片描述
结果正确!以上这些结果就是stack里面常用的接口了。

3.队列的定义

还是老规矩,我们先来看看c++官网文档对queue的介绍文档。
在这里插入图片描述

1.队列也是一种容器适配器,队列满足先进先出的性质,队列从队头出数据,从队尾入数据。

2.如果底层容器是我们自己设计的话,需要满足以下功能接口,empty,size,front,back,push_back,pop_front。

4.队列的使用

queue的使用和stack的使用一样,都是要包头文件

#include <queue>

队列的定义

queue<int> q;

队列的插入数据

queue<int> q;
q.push(1);
q.push(2);
q.push(3);
q.push(4);

队列中数据的遍历

queue也是没有迭代器的,所以queue的遍历操作和stack的遍历操作差不多

	queue<int> q;
	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);

	while (!q.empty())
	{
		int top = q.front();//取队头的数据
		cout << top << " ";
		q.pop();//让队头进行迭代
	}

代码的预期结果应该是1 2 3 4,那么我们来看看是不是这样
在这里插入图片描述

取队尾的元素

queue<int> q;
q.push(1);
q.push(2);
q.push(3);
q.push(4);

cout << q.back() << endl;

在这里插入图片描述

求队列元素的个数

queue<int> q;
q.push(1);
q.push(2);
q.push(3);
q.push(4);

cout << q.size() << endl;

在这里插入图片描述

5.stack的模拟实现

通过以上的知识,我们已经懂得了栈和队列的使用了,那么接下来,我们需要模拟栈和队列的实现了。

首先,我们需要定义一个命名空间,防止和库里面的冲突

namespace ljy
{

}

再声明模板(不懂得可以看模板那一篇博客)

//T表示stack里面数据的类型,Container表示底层的容器
template<class T,class Container>

再定义类模板和声明底层容器的对象

template<class T,class Container>//T表示stack里面数据的类型,Container表示底层的容器
class stack
{
private:
	Container _con;//声明底层容器的对象
};

实现插入接口

public:
	void push(const T& x)
	{
		_con.push_back(x);//调用底层容器的插入数据的接口
	}

实现删除栈顶数据的接口

void pop()
{
	_con.pop_back();//调用底层容器的删掉数据的接口
}

实现求栈的大小

size_t size()
{
	return _con.size();//调用底层容器的求数据个数的接口
}

实现栈判空

bool empty()
{
	return _con.empty();//调用底层容器的判断是否为空的接口
}

实现取栈顶的数据

T& top()
{
	return _con.back();//栈是后进先出
}

测试代码1


		void test_stack1()
		{
			//定义一个栈,底层容器是数组
			stack<int, vector<int>> st1;
			st1.push(1);
			st1.push(2);
			st1.push(3);

			while (!st1.empty())
			{
				int top = st1.top();
				cout << top << " ";
				st1.pop();
			}
			cout << endl;
		}

执行代码看看有没有问题

#include "stack.h"
int main()
{
	ljy::test_stack1();
	return 0;
}

在这里插入图片描述

测试代码2

void test_stack2()
{
	//定义一个栈,底层容器是数组
	//stack<int, vector<int>> st1;
	//定义一个栈,底层容器是链表
	stack<int, list<int>> st1;
	st1.push(1);
	st1.push(2);
	st1.push(3);

	while (!st1.empty())
	{
		int top = st1.top();
		cout << top << " ";
		st1.pop();
	}
	cout << endl;
}
#include "stack.h"
int main()
{
	ljy::test_stack2();
	return 0;
}

在这里插入图片描述

结论:无论是数组还是链表都可以作为底层容器来模拟实现栈,所以可以推导出栈就是一个容器适配器!!!

6.queue模拟实现

queue的模拟实现和stack的模拟实现非常相似,只是队尾入,队头出而已。

#pragma once
#include <iostream>
#include <list>
#include <vector>
using namespace std;

namespace ljy
{
	template<class T, class Container>//T表示queue里面数据的类型,Container表示底层的容器
	class queue
	{
	public:
		void push(const T& x)//队尾入
		{
			_con.push_back(x);//调用底层容器的插入数据的接口
		}
		void pop()//队头出
		{
			_con.pop_front();//调用底层容器的删掉数据的接口
		}
		size_t size()
		{
			return _con.size();//调用底层容器的求数据个数的接口
		}
		bool empty()
		{
			return _con.empty();//调用底层容器的判断是否为空的接口
		}
		T& front()//取队头数据
		{
			return _con.front();//队列是先进先出
		}
		T& back()//取队尾数据
		{
			return _con.back();//队列是先进先出
		}

	private:
		Container _con;
	};
}

测试代码

void test_queue()
{
	queue<int, vector<int>> q;
	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);

	while (!q.empty())
	{
		cout << q.front() << " ";
		q.pop();
	}
	cout << endl;
}

看一下运行结果有没有问题
在这里插入图片描述
直接报错了,我们看看报错内容,是头删出问题了,我们知道vector是不支持头删了,因为vector头删需要挪动数据,效率太低了,由于我们实现queue底层是使用vector容器,所有就直接报错了,我们把vector换成list看还有没有问题。

#pragma once
#include <iostream>
#include <list>
#include <vector>
using namespace std;

namespace ljy
{
	template<class T, class Container>//T表示queue里面数据的类型,Container表示底层的容器
	class queue
	{
	public:
		void push(const T& x)//队尾入
		{
			_con.push_back(x);//调用底层容器的插入数据的接口
		}
		void pop()//队头出
		{
			_con.pop_front();//调用底层容器的删掉数据的接口
		}
		size_t size()
		{
			return _con.size();//调用底层容器的求数据个数的接口
		}
		bool empty()
		{
			return _con.empty();//调用底层容器的判断是否为空的接口
		}
		T& front()//取队头数据
		{
			return _con.front();//队列是先进先出
		}
		T& back()//取队尾数据
		{
			return _con.back();//队列是先进先出
		}

	private:
		Container _con;
	};

	void test_queue()
	{
		queue<int, list<int>> q;
		q.push(1);
		q.push(2);
		q.push(3);
		q.push(4);

		while (!q.empty())
		{
			cout << q.front() << " ";
			q.pop();
		}
		cout << endl;
	}
}

在这里插入图片描述
换成list就没问题了

7.deque容器

老规矩,我们先来看看有关deque容器的文档。
在这里插入图片描述
deque叫双端队列,但它不是队列,而是一种双开口,连续的空间的数据结构,那什么是双开口呢?双开口就是可以在头和在尾插入和删除数据,那么deque相比于vector效率就高很多了,deque相比于list空间的利用率较高。
在这里插入图片描述

deque的缺点

我们知道C++是一门极度注重效率的语言,deque虽然结合了list和vector的优点,但是deque并没有完全继承二者的优点,相比于二者各自的优点还是差点意思,所以deque代替不了vector和list
我们可以看看deque的随机访问和vector随机访问相差的时间
在这里插入图片描述

总结

以上就是关于STL中的stack和queue的全部内容,希望各位老铁看了这篇文章能有所收获。


http://www.kler.cn/a/529313.html

相关文章:

  • 纯后训练做出benchmark超过DeepseekV3的模型?
  • matlab快速入门(2)-- 数据处理与可视化
  • 小程序设计和开发:什么是竞品分析,如何进行竞品分析
  • https的原理
  • Signature
  • 华为Ascend产品
  • 课设:【ID0022】火车票售票管理系统(前端)
  • Qt 5.14.2 学习记录 —— 이십이 QSS
  • 【AI文章解读】《No, DeepSeek Is Not A ‘Sputnik Moment’》
  • 信息学奥赛一本通 ybt 1608:【 例 3】任务安排 3 | 洛谷 P5785 [SDOI2012] 任务安排
  • 制造业数字化转型:从标准化设备到数据与智能算法的共生革命
  • 《基于单中心损失监督的频率感知判别特征学习用于人脸伪造检测 》学习笔记
  • PostgreSQL 数据库视图基础操作
  • tf.Keras (tf-1.15)使用记录1-基础模型创建的两种方法
  • 【股票数据API接口48】如何获取股票最新分时BOLL数据之Python、Java等多种主流语言实例代码演示通过股票数据接口获取数据
  • 【Python】理解Python中的协程和生成器:从yield到async
  • PostgreSQL 数据库备份与还原
  • 如何使用SliverList组件
  • 数据分析系列--⑨RapidMiner训练集、测试集、验证集划分
  • 拉格朗日定理
  • C++编程语言:抽象机制:模板(Bjarne Stroustrup)
  • 【网站建设:HTTPS - 如何生成免费SSL证书,并自动更新】
  • 【自开发工具介绍】SQLSERVER的ImpDp和ExpDp工具01
  • RabbitMQ持久化队列配置修改问题
  • python-leetcode-二叉搜索树迭代器
  • 基于微信小程序的酒店管理系统设计与实现(源码+数据库+文档)