栈、队列总结

9 篇文章 0 订阅
1 篇文章 0 订阅

     描述:后进先出

     实现:可以用链表,数组

应用

A:括号匹配验证

实现:

    对于左括号进栈,对于右括号判断栈是否为空,若为空,则匹配失败,否则出栈。

对于只用一种括号的情况:有另一种改进方式,其实可用一个计数变量,初始化为0,直接统计左单括号即可,不用存储括号类型。

B:进制转换

C:算术表达式的计算

    用两个栈:一个存储符号,一个存储数值

D:递归的应用,保存断点  

E:深度优先搜索

F:单调栈

题目描述:给定一个连续的不同高度的矩形,求能合并的最大矩形面积点击打开poj题目链接

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define N 100010
using namespace std;
struct Node
{
    int id;
    int num;
}s[N];
struct ST
{
    int b;
    int e;
    int sum;
}c[N];
long long a[N];
int main()
{
    //freopen("in.txt","r",stdin);
    int n;
    while( scanf("%d",&n),n )
    {
        for( int i=1; i<=n; i++ )
        {
            scanf("%lld",&a[i]);
        }
        int top=0,j;
        s[0].num=0;s[0].id=0;
        for( int i=1; i<=n; i++ )
        {
            for(j=top; j>=0; j-- )
            {
                if( a[i]>s[j].num) break;
                else
                {
                    c[s[j].id].e=i-1;
                }
            }
            s[j+1].id=i;s[j+1].num=a[i];
            top=j+1;c[i].b=s[top-1].id+1;
        }
        for( int i=0; i<=top; i++ ) c[s[i].id].e=n;
        long long ans=0;
        for( int i=1; i<=n; i++ )
        {
            long long sum=(c[i].e-c[i].b+1)*a[i];
            if( sum>ans ) ans=sum;
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

给定输入顺序为1~N..可用一个栈操作判断能否得到给定的输出顺序点击打开poj题目链接

#include <iostream>
#include <cstdio>
#include <cstring>
#define N 1010
using namespace std;
int main()
{
    //freopen("in.txt","r",stdin);
    int a[N],b[N],n;
    while( scanf("%d",&n),n )
    {
        while( scanf("%d",&a[0]))
        {
            bool flag=true;
            if( a[0]==0 ) break;
            for( int i=1; i<n; i++ )
            scanf("%d",&a[i]);
            int i=1,j=0,top=0;
            while( i<=n )
            {
                if( i!=a[j] )
                {
                    b[top++]=i;i++;
                }
                else j++,i++;
                while( top>0&&j<n&&b[top-1]==a[j] ) j++,top--;
                //i++;
            }
            if( top>0 ) printf("No\n");
            else printf("Yes\n");
        }
        printf("\n");
    }
    return 0;
}

 

队列

描述:先进先出,正由于这个思想,经常用来做缓冲

实现:数组,链表

A: 顾名思义,用来排队。比如舞伴配对问题

       假设在周末舞会上,男士们和女士们进入舞厅时,各自排成一队。跳舞开始时,依次从男队和女队的队头上各处一人配成舞伴。若两队初始人数不相同,则较长的那一对中未配对者等待下一轮舞曲。请模拟上述舞伴配对问题。

B:缓冲队列,用于操作系统中进程调度缓冲

C:优先级队列 ,用堆实现,根据优先级进行进程调度

D:用于广度优先搜索,比如迷宫问题点击打开poj题目链接

        给定n,k,求最少通过多少次 n+1,n-1 ,n*2 操作使得n==k点击打开poj题目链接

#include<iostream>
#include<cstring>
#define N 200003
using namespace std;
typedef struct {
    int x;
    int step;
}Node;
Node queue[N];
int mark[N],a,b;
int bfs(){
    Node temp;
    memset(mark,0,sizeof(mark));
    int front,rear,i,j;
    front=rear=0;
    queue[rear].x=a;
    queue[rear++].step=0;
    while(front<rear){
        temp=queue[front++];
        if(temp.x==b){
            return temp.step;
        }
        if((temp.x-1)<N&&!mark[temp.x-1]){
            mark[temp.x-1]=1;
            queue[rear].x=temp.x-1;
            queue[rear++].step=temp.step+1;
        }
        if((temp.x+1)<N&&!mark[temp.x+1]){
            mark[temp.x+1]=1;
            queue[rear].x=temp.x+1;
            queue[rear++].step=temp.step+1;
        }
        if((temp.x*2)<N&&!mark[temp.x*2]){
            mark[temp.x*2]=1;
            queue[rear].x=temp.x*2;
            queue[rear++].step=temp.step+1;
        }
    }
    return -1;
}
int main(){
    cin>>a>>b;
    cout<<bfs()<<endl;
}

E:循环队列

F:双端队列,队头和对尾都可进可出

G:单调队列,队列元素保持单调性的队列

        给定n个数,从左到右每次选取m个数,求这m个数中的最大值和最小值。点击打开poj题目链接

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define INF ~0u>>1
#define OO -0x7fffffff
#define N 1000010
using namespace std;
int a[N], q[N], d[N];
int main()
{
    int n ,k;
    while( scanf("%d%d",&n,&k)!=EOF )
    {
        for( int i = 0; i < n; i ++ ){
            scanf("%d",&a[i]);
        }
        int front = 0, rear = 0;
        d[rear] = 0;
        q[rear++] = a[0]+1;
        for( int i = 0; i < n; i ++ )
        {
            while ( a[i] < q[rear-1] && rear>front ) rear --;
            d[rear] = i;
            q[rear++] = a[i];
            if( i>=k-1 )
            {
                if( n != i+1 ) printf("%d ",q[front]);
                else printf("%d\n",q[front]);
                if( d[front] == i-k+1 ) front++;
            }
        }
        front = rear = 0;
        d[rear] = 0;
        q[rear++] = a[0]-1;
        for( int i = 0; i < n; i ++ )
        {
            while ( a[i] > q[rear-1] && rear>front ) rear --;
            d[rear] = i;
            q[rear++] = a[i];
            if( i>=k-1 )
            {
                if( n != i+1 ) printf("%d ",q[front]);
                else printf("%d\n",q[front]);
                if( d[front] == i-k+1 ) front++;
            }
        }
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值