STL之栈队列以及容器适配器

x33g5p2x  于2022-01-07 转载在 其他  
字(2.9k)|赞(0)|评价(0)|浏览(148)

1.1栈

1.2栈的使用

1.3容器适配器

1.4栈模拟实现

2.1 queue

2.2queue的使用

2.3queue的模拟实现

1.栈

  1. stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行

元素的插入与提取操作。
2. stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定

的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。
3. stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下

操作:
empty:判空操作

back:获取尾部元素操作
push_back:尾部插入元素操作

pop_back:尾部删除元素操作
4.标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器,

默认情况下使用deque。

1.2栈的使用

bool  empty()       //栈是否为空

void pop()            //从栈顶删除元素(栈不能为空)

void push()          //在栈顶插入一个新的元素

int size()              //栈的数据量

T & top()             //返回栈顶部的引用(栈不能为空)
 

stack<int>stk;
		stk.push(1);
		stk.push(2);
		stk.push(3);
		while (!stk.empty()) {
			cout << stk.top() << " ";
			stk.pop();
		}

1.3容器适配器

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

STL中stack和queue的底层结构

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

 1.4栈模拟实现

template<class T,class Container>
	class stack {
	public:
		void push(const T& x) {
			_con.push_back(x);
		}
		void pop() {
			_con.pop_back();
		}
		size_t size() {
			return _con.size();
		}
		T& top() {
			return _con.back();
		}
		bool empty() {
			return _con.empty();
		}
	private:
		Container _con;
	};

测试代码:

void Test_stack() {
		stack<int,vector<int>>stk;
		stk.push(1);
		stk.push(2);
		stk.push(3);
		while (!stk.empty()) {
			cout << stk.top() << " ";
			stk.pop();
		}

	}

当然我们也可以使用list做为容器适配器

void Test_stack() {
		stack<int,list<int>>stk;
		stk.push(1);
		stk.push(2);
		stk.push(3);
		while (!stk.empty()) {
			cout << stk.top() << " ";
			stk.pop();
		}

	}

 2. queue

1.队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端

提取元素。
2.队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的

成员函数来访问其元素。元素从队尾入队列,从队头出队列。
3.底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操

作:
empty:检测队列是否为空

size:返回队列中有效元素的个数
front:返回队头元素的引用

back:返回队尾元素的引用
push_back:在队列尾部入队列

pop_front:在队列头部出队列
4.标准容器类deque和list满足了这些要求。默认情况下,如果没有为queue实例化指定容器类,则使用标 准容器deque。

 2.1queue的使用

#include<queue>
#include<iostream>
using namespace std;
int main() {
	queue<int>q;
	q.push(1);
	q.push(2);
	q.push(3);
	while (!q.empty()) {
		cout << q.front() << " ";
		q.pop();
	}
	return 0;
}

2.3queue的模拟实现

template<class T,class Container>
	class queue {
	public:
		bool empty() {
			return _con.empty();
	    }
		bool size() {
			return _con.size();
		}
		void push(const T&val) {
			_con.push_back(val);
		}
		void pop() {
			_con.pop_front();
		}
		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);
		while (!q.empty()) {
			cout << q.front() << " ";
			q.pop();
		}
 }

注意:queue的容器适配器不能使用vector因为vector没有提供pop_front.

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

结合了deque的优点,而完美的避开了其缺陷。

相关文章