栈与队列
1)在C++中使用标准库实现栈和队列结构
栈是以底层容器来完成其所有的工作,对外提供统一的接口,底层容器是可以插拔的(说明可以使用哪种容器来实现栈的功能)。因此STL中栈一般归类为container adapter(容器适配器)。栈的底层实现可以是vector,deque,list 都是可以的, 主要就是数组和链表的底层实现。
stack中所有元素的进出都必须符合“先进后出”的逻辑,只有stack的顶端的元素,才有机会被外界取用。stack不提供走访功能,也不提供迭代器。
队列中先进先出的数据结构,同样不允许有遍历行为,不提供迭代器, SGI STL中队列一样是以deque为缺省情况下的底部结构。也可以指定list 为起底层实现,初始化queue的语句如下:
std::stack<int, std::vector<int> > third; // 使用vector为底层容器的栈
std::queue<int, std::list<int>> third; // 定义以list为底层容器的队列
2)使用栈来实现队列
由于队列是先入先出,而栈是先进后出,因此要实现队列,需要两个栈来实现,一个为输入栈,一个为输出栈。不放这么理解:
在push数据的时候 ,只需要将数据放入输入栈就行,在pop的时候,首先让push栈的数据先全按出栈顺序依次压入输出栈,然后再pop出去。如果输入栈和输出栈都为空的话,则直接从出栈弹出数据就ok了。
class MyQueue {
public:
//定义两个栈,作为输入栈和输出栈
stack<int> stackIn;
stack<int> stackOut;
MyQueue() {
}
void push(int x) {
stackIn.push(x);
}
int pop() {
if(stackOut.empty()){
while(!stackIn.empty()){
stackOut.push(stackIn.top());
stackIn.pop();
}
}
int result = stackOut.top();
stackOut.pop();
return result;
}
int peek() {
int res = this->pop();
stackOut.push(res);
return res;
}
bool empty() {
return stIn.empty() && stOut.empty();
}
};
3)使用队列来实现栈
队列是先进先出的规则,把一个队列中的数据导入另一个队列中,数据的顺序并没有变,并没有变成先进后出的顺序。依然还是要用两个队列来模拟栈,只不过没有输入和输出的关系,而是另一个队列完全用来备份的!
可以这么理解:push操作:1,2,3,进入第一个队列:3-2-1。那么现在我需要pop操作,应该将1,2存入到第二个队列当中,然后第一个队列只剩3,执行出队皆可,最后要把第二个队列复制给第一个队列:
class MyStack {
public:
queue<int> que1;
queue<int> que2; // 辅助队列,用来备份
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
que1.push(x);
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int size = que1.size();
size--;
while (size--) { // 将que1 导入que2,但要留下最后一个元素
que2.push(que1.front());
que1.pop();
}
int result = que1.front(); // 留下的最后一个元素就是要返回的值
que1.pop();
que1 = que2; // 再将que2赋值给que1
while (!que2.empty()) { // 清空que2
que2.pop();
}
return result;
}
/** Get the top element. */
int top() {
return que1.back();
}
/** Returns whether the stack is empty. */
bool empty() {
return que1.empty();
}
};
栈和队列 STL
下面是 stack 容器可以提供的一套完整操作:
queue 和 stack 有一些成员函数相似,但某些情况下,功能有些不同: