代码随想录算法训练营第10天 | 232.用栈实现队列 225. 用队列实现栈

栈与队列理论基础

  1. C++ 中的 stack 是容器吗?
    不是容器,而是容器适配器,因为 stack 是通过底层容器实现的,对外提供统一的接口,底层容器是可插拔的,也就是说我们可以控制用哪种容器来实现栈的功能。
  2. 我们使用的 stack 属于哪个版本的 STL?
    首先要知道 STL 有哪些版本,HP STL 是 C++ STL 的第一个实现版本,而且开放源代码,其他的 STL 都是基于 HP 来实现的;P.J.Plauger STL 基于 HP STL 实现,被 Visual C++ 编译器使用,不开源;SGI STL 也是基于 HP STL 实现,被 Linux 的 C++ 编译器 GCC 使用,源码可读性高。
    我们使用的是 SGI STL,在这个版本中栈提供pushpop等接口,
  3. 我们使用的 STL 中 stack 是如何实现的?
    作为容器适配器,stack 是通过底层容器实现的,我们可以指定用哪种容器,主要就是数组或链表的底层实现,比如 vector、deque、list,下图很清楚的表示了 stack 实现的样式。
    代码随想录算法训练营第10天 | 232.用栈实现队列 225. 用队列实现栈_第1张图片
std::stack<int, std::vector<int>>
std::queue<int, std::list<int>>

当我们没指定底层容器时,默认是通过 deque 实现的。

  1. stack 提供迭代器来遍历 stack 空间吗?
    所有元素遵循先入后出的原则,所以不支持走访功能,也不提供迭代器遍历栈空间。

用栈实现队列

代码随想录算法训练营第10天 | 232.用栈实现队列 225. 用队列实现栈_第2张图片
因为只能使用栈的基本操作,即只能先入后出,但又想实现先入先出。一个栈 IO 方向是不对的,所以必须用两个栈,我们就能把 IO 顺序调整过来。在具体实现时要注意两个栈的使用顺序,一个是输入栈,一个是输出栈

class MyQueue{
public:
	stack<int> stack_in;
	stack<int> stack_out;
	MyQueue(){
	
	}
	void push(int x){
		stack_in.push(x);
	}
	int pop(){
		if(stack_out.empty()){
			while(!stack_in.empty()){
				int x = stack_in.top();
				stack_in.pop();
				stack_out.push(x);
			}
		}
		int x = stack_out.top();
		stack_out.pop();
		return x;
	}
	int peek(){
		int x = this->pop();
		stack_out.push(x);
		return x;
	}
	bool empty(){
		return stack_in.empty() && stack_out.empty();
	}
};

用队列实现栈

代码随想录算法训练营第10天 | 232.用栈实现队列 225. 用队列实现栈_第3张图片
类比用栈实现队列,我们同样考虑使用两个队列来实现栈,但是需要注意的是,由于队列先入先出的性质,两个队列也不会像两个栈那样改变 IO 顺序,变成先入后出。这时我们可以将一个队列的元素推出,另一个队列备份这些元素,等到第一个队列只剩最后一个元素时,这个元素就是按栈的性质应该输出的元素。所以两个队列实现栈和两个栈实现队列还是不同的,两个栈可以改变 IO 顺序,但两个队列中一个只是起到备份的作用。

class MyStack{
public:
	queue<int> que1;
	queue<int> que2;
	MyStack(){
	
	}
	void push(int x){
		que1.push(x);
	}
	int pop(){
		int size = que1.size();
		for(int i = 0; i < size - 1; i++){
			que2.push(que1.front());
			que1.pop();
		}
		int x = que1.front();
		que1.pop();
		que1 = que2;
		while(!que2.empty()){
			que2.pop();
		}
		return x;
	}
	int top(){
		int x = this->pop();
		que1.push(x);
		return x;
	}
	bool empty(){
		return que1.empty();
	}
};

注:由于另外的队列只是起备份作用,那么我们将推出的元素备份在队列本身也是可行的,这样就其实只需要一个队列就可实现。

class MyStack{
public:
	queue<int> que;
	MyStack(){
	
	}
	void push(int x){
		que.push(x);
	}
	int pop(){
		int size = que.size();
		// 遍历到最后一个元素之前,最后一个元素使我们要输出的
		for(int i = 0; i < size - 1; i++){
			que.push(que.front());
			que.pop();
		}
		int x = que.front();
		que.pop();
		return x;
	}
	int top(){
		int x = this->pop();
		que.push(x);
		return x;
	}
	bool empty(){
		return que.empty();
	}
};

你可能感兴趣的:(算法)