栈结构之双栈

如果让你用栈实现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;

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值