一 栈与队列的理论基础
-
栈和队列是STL(C++标准库)里面的两个数据结构。这里以被Linux的C++编译器GCC所采用 SGI STL作为了解对象。
-
栈提供push 和 pop 等等接口,栈不提供走访功能,也不提供迭代器(iterator)。 不像是set 或者map 提供迭代器iterator来遍历所有元素。**栈是以底层容器完成其所有的工作,对外提供统一的接口,底层容器是可插拔的(也就是说我们可以控制使用哪种容器来实现栈的功能)。**所以STL中栈往往不被归类为容器,而被归类为container adapter(容器适配器)。
-
栈的内部结构,栈的底层实现可以是vector,deque,list 都是可以的, 主要就是数组和链表的底层实现。**SGI STL,如果没有指定底层实现的话,默认是以deque为缺省情况下栈的底层结构。**当然也可以指定vector为栈的底层实现,如:
std::stack<int, std::vector<int> > third;
-
队列中先进先出的数据结构,同样不允许有遍历行为,不提供迭代器, **SGI STL中队列一样是以deque为缺省情况下的底部结构。**所以STL 队列也不被归类为容器,而被归类为container adapter( 容器适配器)
二 232 用栈实现队列
采用两个栈分别作为输入栈和输出栈,从而实现队列
class MyQueue {
public:
stack<int> stackin;
stack<int> stackout;
MyQueue() {
}
void push(int x) {
stackin.push(x);
}
int pop() {
while(!stackin.empty()){
stackout.push(stackin.top());
stackin.pop();
}
int res = stackout.top();
stackout.pop();
while(!stackout.empty()){
stackin.push(stackout.top());
stackout.pop();
}
return res;
}
int peek() {
while(!stackin.empty()){
stackout.push(stackin.top());
stackin.pop();
}
int res = stackout.top();
while(!stackout.empty()){
stackin.push(stackout.top());
stackout.pop();
}
return res;
}
bool empty() {
return stackin.empty();
}
};
三 225 用队列实现栈
方法一:用两个队列que1和que2实现队列的功能,que2其实完全就是一个备份的作用,把que1最后面的元素以外的元素都备份到que2,然后弹出最后面的元素,再把其他元素从que2导回que1。
方法二:**一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时再去弹出元素就是栈的顺序了。**有点类似于循环队列。
class MyStack {
public:
queue<int> que;
MyStack() {
}
void push(int x) {
que.push(x);
}
int pop() {
int count = que.size() -1 ;
//将最后一个元素前的所有元素都重新插入到队列后面
while(count--){
que.push(que.front());
que.pop();
}
// 此时弹出的元素栈顶的元素
int result = que.front();
que.pop();
return result;
}
int top() {
int count = que.size() -1 ;
while(count--){
que.push(que.front());
que.pop();
}
// 此时弹出的元素栈顶的元素
int result = que.front();
que.push(que.front());
que.pop();
return result;
}
bool empty() {
return que.empty();
}
};
四 总结
- 用栈实现队列需要两个栈,输入栈和输出栈;用队列实现栈可以用一个或者两个队列
- 在SGI STL中栈和队列一样是以deque为缺省情况下的底部结构,栈和队列并不算是容器,而是被划分为container adapter( 容器适配器)