STL容器适配器之<queue>

Posted SiveenWS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STL容器适配器之<queue>相关的知识,希望对你有一定的参考价值。

文章目录

测试环境

系统:ubuntu 22.04.2 LTS 64位
gcc版本:11.3.0
编辑器:vsCode 1.76.2

queue介绍

  1. queue为容器适配器。
  2. 支持在末端插入元素,在首端删除元素。
  3. 不支持随机访问。
  4. 先进先出规则(FIFO)
  5. 默认基础容器为deque,还可以使用list作为基础容器,或者支持front()、pop_front()、back()、push_buck()的其他容器。

头文件

#include <queue>

模块类定义

_Tp:表示存储的元素数据类型
_Alloc:表示所存储分配器的类型,负责元素内存的分配和释放。可选参数,一般不使用。

template<typename _Tp, typename _Sequence = deque<_Tp> > class queue;

对象构造

/*构造默认栈对象*/
std::queue<int> queueInt;
/*构造以deque作为基础容器的栈*/
std::queue<int, std::deque<int> > deqQueue;
/*构造以deque作为基础容器的栈*/
std::queue<int, std::vector<int> > vctQueue;
/*构造以list作为基础容器的栈*/
std::queue<int, std::list<int> > lstQueue;
/*从链表中构造对象并将链表中的数据作为队列数据*/
std::list<int> lst(1,2,3);
std::queue<int, std::list<int> > lstQueue1(lst);

初始化

/*初始化*/
deqQueue.push(100);
deqQueue.push(200);
deqQueue.push(300);

元素访问

函数名返回值功能
front()首元素的引用获取首元素,队列为空时返回值不确定
back()尾元素的引用获取末尾元素,队列为空时返回值不确定
/*获取队头元素*/
int &iFrontVal = deqQueue.front();
std::cout << iFrontVal << std::endl;
/*修改队头元素*/
iFrontVal = 66;
std::cout << deqQueue.front() << std::endl;
/*获取队尾元素*/
int &iBackVal = deqQueue.back();
std::cout << iBackVal << std::endl;
/*修改队尾元素*/
iBackVal = 88;
std::cout << deqQueue.back() << std::endl;

元素插入和删除

函数返回值功能
pop()删除队列头元素
push()队列尾插入元素
/*在链表头插入元素*/
deqQueue.push(88);
/*删除链表头部元素*/
deqQueue.pop();

容器大小

函数返回值功能
empty()bool判断当前容器是否为空,为空返回true,否则返回false
size()std::size_t获取当前容器中的元素数量
/*判断队列是否为空*/
std::cout << std::boolalpha << queueInt.empty() << std::endl;
/*获取队列中元素数量*/
std::cout << deqQueue.size() << std::endl;

迭代器

不支持

其他函数

函数名返回值功能
swap()交换两个容器的元素
/*交互两个容器元素的值,无返回值*/
std::queue<int> queSwap1 = 1,2,3,4,5;
std::queue<int> queSwap2 = 5,4,3,2,1;
/*方式1, queSwap1=5,4,3,2,1, queSwap2=1,2,3,4,5*/
queSwap1.swap(queSwap2);
/*方式2,queSwap1=1,2,3,4,5, queSwap2=5,4,3,2,1*/
std::swap(queSwap1,queSwap2);

STL容器适配器stack和queue

STL容器适配器——stack、queue

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


前言

stack和queue是作为STL的容器适配器被实现的,容器适配器暨是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层。


一、stack

1.基本使用

先来看一下MSDN里面对stack的简单介绍示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
我们再来看一下stack简单的使用。

void main()
{
	stack<int> st;//容器适配器
	for (int i = 1; i <= 10; ++i)//将1到10顺序入栈
	{
		st.push(i);
	}
	cout << "st.size = " << st.size() << endl;
	while (!st.empty())//顺序出栈
	{
		int value = st.top();
		st.pop();
		cout << value << endl;
	}
	//无法通过迭代器访问
}	

给个题理解一下。
155.最小栈
题解:

class MinStack {
public:
    /** initialize your data structure here. */
    MinStack() 
    {}
    
    void push(int val) 
    {
        data_st.push(val);
        if(min_st.empty() || val<=min_st.top())
        min_st.push(val);
    }
    
    void pop() 
    {
        int val = data_st.top();
        data_st.pop();
        if(val == min_st.top())
            min_st.pop();
    }
    
    int top() 
    {
        return data_st.top();
    }
    
    int getMin() 
    {
        return min_st.top();
    }
private:
    stack<int> data_st;
    stack<int> min_st;
};

2.模拟实现

从栈的接口中可以看出,栈实际是一种特殊的vector,因此使用vector完全可以模拟实现stack。

namespace LJL
{
	template<class _Ty>
	class stack
	{
	public:
		stack()
		{}
		~stack()
		{}
	public:
		bool empty()const
		{
			return _C.empty();
		}
		size_t size()const
		{
			return _C.size();
		}
		_Ty& top()
		{
			return _C.back();
		}
		const _Ty& top()const
		{
			return _C.back();
		}
		void push(const _Ty &x)
		{
			_C.push_back(x);
		}
		void pop()
		{
			_C.pop_back();
		}
	private:
		vector<_Ty> _C;//若要使用list模拟只需要把vector改为list
	};
}

二、queue

1.基本使用

在这里插入图片描述
注意这里的msdn有误,队列无top一说,队列的队头为front
代码演示:

void main()
{
	queue<int> q;//容器适配器
	for (int i = 1; i <= 10; ++i)//将1到10顺序入栈
	{
		q.push(i);
	}
	cout << "q.size = " << q.size() << endl;
	while (!q.empty())//顺序出栈
	{
		int value = q.front();
		q.pop();
		cout << value << endl;
	}
	//无法通过迭代器访问
}	

在这里插入图片描述

2.模拟实现

因为queue的接口中存在头删和尾插,因此使用vector来封装的效率太低,故可以借助list来模拟实现。
代码如下:

#include <list>
namespace LJL
{
	template<class T>
	class queue
	{
	public:
		queue() {}
		void push(const T& x) { _c.push_back(x); }
		void pop() { _c.pop_front(); }
		T& back() { return _c.back(); }
		const T& back()const { return _c.back(); }
		T& front() { return _c.front(); }
		const T& front()const { return _c.front(); }
		size_t size()const { return _c.size(); }
		bool empty()const { return _c.empty(); }
	private:
		list<T> _c;
	};
}

在系统中stack和queue是用容器双端队列deque来模拟的。

#include <deque>
namespace LJL
{
	template<class _Ty,class Cont=deque<_Ty>>
	class stack
	{
	public:
		stack()
		{}
		~stack()
		{}
	public:
		bool empty()const
		{
			return _C.empty();
		}
		size_t size()const
		{
			return _C.size();
		}
		_Ty& top()
		{
			return _C.back();
		}
		const _Ty& top()const
		{
			return _C.back();
		}
		void push(const _Ty &x)
		{
			_C.push_back(x);
		}
		void pop()
		{
			_C.pop_back();
		}
	private:
		Cont _C;
	};

	template<class _Ty, class Cont=deque<_Ty>>
	class queue
	{
	public:
		queue()
		{}
		~queue()
		{}
	public:
		bool empty()const
		{
			return _C.empty();
		}
		size_t size()const
		{
			return _C.size();
		}
		_Ty& front()
		{
			return _C.front();
		}
		_Ty& back()
		{
			return _C.back();
		}
		void pop()
		{
			_C.pop_front();
		}
		void push(const _Ty &x)
		{
			_C.push_back(x);
		}
	private:
		Cont _C;
	};
}

3.deque双端队列

是一种双开口的“连续”空间的数据结构(实际并不是连续的,而是由一段段连续的小空间拼接而成的,类似于一个动态的二维数组),可以再头尾两端进行插入和删除操作,且时间复杂度为O(1)而vector为O(n),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率较高,因为list不仅存储数据而且还需存储前后关系指针。
在这里插入图片描述

相对于普通queue而言,deque既可以尾插也可以头插,既可以头删也可以尾删。而queue只能尾插和头删。
代码演示:

void main()
{
	deque<int> dq;
	for (int i = 1; i <= 3; ++i)
	{
		dq.push_back(i);//尾插
	}
	for (int i = 3; i >= 1; --i)
	{
		dq.push_front(i);//头插
	}
	for (const auto & e : dq)
	{
		cout << e << " ";
	}
	cout << endl;
	while (!dq.empty())
	{
		cout << dq.back() << endl;
		dq.pop_back();
	}
}

在这里插入图片描述
deque的缺陷:
不适合遍历,因为在遍历时,deque的迭代器要频繁检测其是否移动到某段小空间的边界,导致效率低下,目前对于queue的应用主要为stack和queue的底层数据结构。


以上是关于STL容器适配器之<queue>的主要内容,如果未能解决你的问题,请参考以下文章

C++STL之stack和queue以及deque详解

STL之容器适配器priority_queue

C++STL之stackqueue的使用和模拟实现+优先级队列(附仿函数)+容器适配器详解

[C/C++]详解STL容器3--stackqueue和priority_queue的功能和模拟实现,deque和容器适配器的介绍

C++从青铜到王者第十五篇:STL之queue类的初识和模拟实现

STL之stack 和 queue