如果让你用栈实现BFS,你是不是又要疯。其实你细想一下,BFS的基本结构是队列,那么这题本质上只是在问你如何用栈实现队列而已。我们知道,队列是让元素按照进队的顺序出队,而栈是按照进栈顺序的逆序出栈,负负得正,两次逆序不久正序了吗?所以显而易见,实现队列的方法就是用双栈。我们设置两个栈in、out。
push:直接将元素放入in栈
pop:
1)如果out栈为空,将in内的所有元素倒入out,再将out的栈顶弹出
2)如果out栈不为空,直接将out栈顶弹出
top:
1)如果out栈为空,将in内的所有元素倒入out,再将out的栈顶元素输出
2)如果out栈不为空,直接将out栈顶弹出
为什么pop和top不为空的时候才能倒?很简单,我们知道倒入out的元素已经被纠正为了正确的顺序,此时如果out不为空却将in内元素倒入的话,顺序就不对了,此时应该在队头的元素被新元素压下去了。
代码:
#include<cstdio>
#include<stack>
using namespace std;
typedef struct{
stack<int>in,out;
int front(){//返回队头元素
if(out.empty()){//倒元素
while(!in.empty()){
out.push(in.top());
in.pop();
}
}
return out.top();
}
void push(int val){
in.push(val);
}
void pop(){
if(out.empty()){//倒元素
while(!in.empty()){
out.push(in.top());
in.pop();
}
}
out.pop();
}
}Queue;
int main(){
Queue que;
que.push(1);
que.pop();
que.push(2);
printf("队头:%d\n",que.front());
que.pop();
que.push(3);
que.push(4);
printf("队头:%d\n",que.front());
que.pop();
que.push(5);
que.push(6);
printf("队头:%d\n",que.front());
}
要求实现一个栈,附加功能是返回栈内存储的所有元素的最小值。
1.对于一个栈来说,至少所有语言封装的栈是不支持遍历操作的,所以如果你想要用遍历的方式返回任意时刻栈内最小元素的话,只能手动实现栈,然而复杂度是O(m*size),m是查询次数,size是栈的平均尺寸。
2.我们做这样一个考虑,如果从第i个数开始,其后进来的数都比第i个数小,那么对于他们来说的查询结果就是第i个数,然而我们要考虑当第i个数出栈之后,如果不遍历呢?简言之就是用另一个结构做记录,然后根据当前的操作结构对记录结构进行修改。
此处用双栈会是一个很简单的方法:开两个栈,一个操作栈,一个data栈,两个栈同时push、pop,data栈内存放的是相同尺寸下,操作栈内的最小值。以下图为例:
操作栈 data栈
维护规则:push
A.data栈为空【操作栈也为空,因为两个栈时同时变换的】,将压入操作栈的数也压入data栈
B.data栈不为空:
1)如果压入操作栈的数比data栈顶元素小,则表示当前入栈了一个比之前最小的数更小的数,那么在data栈压入这个数。
2)如果压入操作栈的数不比data栈顶元素小,则表示并没有入栈一个比之前最小的数更小的数吗,那么直接将data栈的栈顶再压一遍。
维护操作:pop
两个栈同时pop即可。
代码:
#include<stack>
#include<cstdio>
using namespace std;
int main(){
stack<int>op,Min;
int m,opt,x;
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d",&opt);
if(opt&1){//插入
scanf("%d",&x);
if(op.empty()){//空则直接插入
op.push(x);
Min.push(x);
}
else{
x=x<=Min.top()?x:Min.top();
Min.push(x);
op.push(x);
}
}
else{//删除
if(op.empty()){
printf("栈空,删除出错!\n");
}else{
Min.pop();
op.pop();
}
}
if(!Min.empty())
printf("当前栈中最小值:%d",Min.top());
}
return 0;
}