• 【C++】STL详解(七)—— stack和queue的使用及模拟实现


    在这里插入图片描述

    ​📝个人主页@Sherry的成长之路
    🏠学习社区:Sherry的成长之路(个人社区)
    📖专栏链接:C++学习
    🎯长路漫漫浩浩,万事皆有期待

    上一篇博客:【C++】STL详解(六)—— list的模拟实现

    容器适配器

    什么是适配器

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

    在这里插入图片描述

    stack和queue有一点需要注意的是,虽然stack和queue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称为容器适配器,这是因为stack和queue只是对其他容器的接口进行了包装,STL中stack和queue默认使用deque容器。

    在这里插入图片描述

    在stack和queue的类模板声明当中我们就可以看到,它们的模板参数有两个,第一个是stack和queue当中所存储的元素类型,而另一个就是指定使用的容器类型。只不过当我们不指定使用何种容器的情况下,stack和queue都默认使用deque作为指定容器。

    在这里插入图片描述

    学过数据结构后知道,stack和queue既可以使用顺序表实现,也可以使用链表实现。在这里我们若是定义一个stack,并指定使用vector容器,则定义出来的stack实际上就是对vector容器进行了包装

    deque特点:
    在这里插入图片描述

    为什么选择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不仅效率高,而且内存使用率高。

    在这里插入图片描述

    stack

    stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其只能从容器的一端进行元素的插入与提取操作。
    在这里插入图片描述

    stack的定义方式

    方式一: 使用默认的适配器定义栈。

    stack<int> st1;
    
    • 1

    方式二: 使用特定的适配器定义栈。

    stack<int, vector<int>> st2;
    stack<int, list<int>> st3;
    
    • 1
    • 2

    注意: 如果没有为stack指定特定的底层容器,默认情况下使用deque。

    stack的使用

    stack当中常用的成员函数如下:

    成员函数	 功能
    empty	判断栈是否为空
    size	获取栈中有效元素个数
    top   	获取栈顶元素
    push	元素入栈
    pop 	元素出栈
    swap	交换两个栈中的数据
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    示例:

    #include 
    #include 
    #include 
    using namespace std;
    
    int main()
    {
    	stack<int, vector<int>> st;
    	st.push(1);
    	st.push(2);
    	st.push(3);
    	st.push(4);
    	cout << st.size() << endl; //4
    	while (!st.empty())
    	{
    		cout << st.top() << " ";
    		st.pop();
    	}
    	cout << endl; //4 3 2 1
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    queue

    队列是一种容器适配器,专门用在具有先进先出操作的上下文环境中,其只能从容器的一端插入元素,另一端提取元素。
    在这里插入图片描述

    queue的定义方式

    方式一: 使用默认的适配器定义队列。

    queue<int> q1;
    
    • 1

    方式二: 使用特定的适配器定义队列。

    queue<int, vector<int>> q2;
    queue<int, list<int>> q3;
    
    • 1
    • 2

    注意: 如果没有为queue指定特定的底层容器,默认情况下使用deque。

    queue的使用

    queue当中常用的成员函数如下:

    成员函数	功能
    empty	判断队列是否为空
    size	获取队列中有效元素个数
    front	获取队头元素
    back	获取队尾元素
    push	队尾入队列
    pop	    队头出队列
    swap	交换两个队列中的数据
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    示例:

    #include 
    #include 
    #include 
    using namespace std;
    
    int main()
    {
    	queue<int, list<int>> q;
    	q.push(1);
    	q.push(2);
    	q.push(3);
    	q.push(4);
    	cout << q.size() << endl; //4
    	while (!q.empty())
    	{
    		cout << q.front() << " ";
    		q.pop();
    	}
    	cout << endl; //1 2 3 4
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    stack的模拟实现

    知道了容器适配器后,stack的模拟实现就显得相当简单,我们只需要调用所指定容器的各个成员函数即可实现stack的各个函数接口。

    成员函数函数作用实现方法
    push元素入栈调用所指定容器的push_back
    pop元素出栈调用所指定容器的pop_back
    top获取栈顶元素调用所指定容器的back
    size获取栈中有效元素个数调用所指定容器的size
    empty判断栈是否为空调用所指定容器的empty
    swap交换两个栈中的数据调用所指定容器的swap

    实现代码如下:

    namespace sherry //防止命名冲突
    {
    	template<class T, class Container = std::deque<T>>
    	class stack
    	{
    	public:
    		//元素入栈
    		void push(const T& x)
    		{
    			_con.push_back(x);
    		}
    		//元素出栈
    		void pop()
    		{
    			_con.pop_back();
    		}
    		//获取栈顶元素
    		T& top()
    		{
    			return _con.back();
    		}
    		const T& top() const
    		{
    			return _con.back();
    		}
    		//获取栈中有效元素个数
    		size_t size() const
    		{
    			return _con.size();
    		}
    		//判断栈是否为空
    		bool empty() const
    		{
    			return _con.empty();
    		}
    		//交换两个栈中的数据
    		void swap(stack<T, Container>& st)
    		{
    			_con.swap(st._con);
    		}
    	private:
    		Container _con;
    	};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    queue的模拟实现

    同样的方式,我们也是通过调用所指定容器的各个成员函数来实现queue的。

    成员函数函数作用实现方法
    push队尾入队列调用所指定容器的push_back
    pop队头出队列调用所指定容器的pop_front
    front获取队头元素调用所指定容器的front
    back获取队尾元素调用所指定容器的back
    size获取栈中有效元素个数调用所指定容器的size
    empty判断栈是否为空调用所指定容器的empty
    swap交换两个队列中的数据调用所指定容器的swap

    实现代码如下:

    namespace sherry //防止命名冲突
    {
    	template<class T, class Container = std::deque<T>>
    	class queue
    	{
    	public:
    		//队尾入队列
    		void push(const T& x)
    		{
    			_con.push_back(x);
    		}
    		//队头出队列
    		void pop()
    		{
    			_con.pop_front();
    		}
    		//获取队头元素
    		T& front()
    		{
    			return _con.front();
    		}
    		const T& front() const
    		{
    			return _con.front();
    		}
    		//获取队尾元素
    		T& back()
    		{
    			return _con.back();
    		}
    		const T& back() const
    		{
    			return _con.back();
    		}
    		//获取队列中有效元素个数
    		size_t size() const
    		{
    			return _con.size();
    		}
    		//判断队列是否为空
    		bool empty() const
    		{
    			return _con.empty();
    		}
    		//交换两个队列中的数据
    		void swap(queue<T, Container>& q)
    		{
    			_con.swap(q._con);
    		}
    	private:
    		Container _con;
    	};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    总结:

    今天我们比较详细地完成了stack和queue的使用及模拟实现,了解了一些有关的底层原理。接下来,我们将进行STL中priority_queue的学习。希望我的文章和讲解能对大家的学习提供一些帮助。

    当然,本文仍有许多不足之处,欢迎各位小伙伴们随时私信交流、批评指正!我们下期见~

    在这里插入图片描述

  • 相关阅读:
    C语言适不适合新手学习?
    React Three Fiber快速入门
    mysql中选datetime 还是 timestamp呢?
    Pycharm-community-2021版安装和配置
    记录在linux上单机elasticsearch8和kibana8
    SparkStreaming 案例实操 完整使用 (第十七章)
    ps制作gif动图
    tiup cluster display
    excel功能区(ribbonx)编程笔记 4-combobox和dropdown控件
    SharpShooter Reports.Web 7.5 Crack
  • 原文地址:https://blog.csdn.net/m0_73258399/article/details/130735540