zoukankan      html  css  js  c++  java
  • 基础数据结构 ①(栈|队列|链表)

    *Update on 2018/10/8

    一.栈

    两种实现,数组(stl选手现在弃了...)和stl自带的<stack>。

    1)———算术表达式运算

    我们用3*(1-2)为例

    ①后缀表达式(逆波兰式)即为1 2 - 3 *

    建立栈,在将式子中的元素逐一扫描,若遇到数则进栈,遇到运算符则取出栈顶两元素进行计算后进栈。

    ②中缀表达式 即为我们人脑接受的式子

     1 #include<string>
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<stack>
     6 using namespace std;
     7 string cnt;
     8 int n;
     9 stack<char>res;
    10 void solve(string cnt)
    11 {
    12     for(int i=0;i<=cnt.size()-1;i++)
    13     {
    14         if(cnt[i]=='<') cnt[i]='1';
    15         else if(cnt[i]=='>') cnt[i]='2';
    16         else if(cnt[i]=='(') cnt[i]='3';
    17         else if(cnt[i]==')') cnt[i]='4';
    18         else if(cnt[i]=='[') cnt[i]='5';
    19         else if(cnt[i]==']') cnt[i]='6';
    20         else if(cnt[i]=='{') cnt[i]='7';
    21         else if(cnt[i]=='}') cnt[i]='8';
    22     }
    23     for(int i=0;i<=cnt.size()-1;i++)
    24     {
    25         if(cnt[i]<=res.top())
    26         {
    27             if(cnt[i]=='1'||cnt[i]=='3'||cnt[i]=='5'||cnt[i]=='7')
    28             {
    29                 res.push(cnt[i]);
    30             }
    31             else 
    32             {
    33                 printf("NO
    ");
    34                 return ;
    35             }
    36         }
    37         else
    38         {
    39             if(cnt[i]-res.top()<=2&&cnt[i]-res.top()>=0) res.pop();
    40             else 
    41             {
    42             printf("NO
    ");
    43             return ;
    44             }
    45         }
    46     }
    47     if(res.top()<60)
    48     {
    49         printf("NO
    ");
    50         return ;
    51     } 
    52     printf("YES
    ");return;
    53 }
    54 void init()
    55 {
    56     for(int i=1;i<=res.size();i++)
    57      res.pop();
    58 }
    59 int main()
    60 {
    61     freopen("strs.in","r",stdin);
    62     freopen("strs.out","w",stdout);
    63     scanf("%d",&n);
    64     for(int i=1;i<=n;i++)
    65     {
    66         cin>>cnt;
    67         res.push('~');
    68         solve(cnt);
    69         init();
    70     }
    71     fclose(stdin);
    72     fclose(stdout);
    73     return 0;
    74 }
    年轻的时候还能写的表达式@!#¥%#@#

    2)———求进出栈可能序列种数,进栈的顺序为1~N。

    法一:最直接的想法是搜索(二进制枚举当前进栈/在栈非空的情况下出栈两种情况),但数据较大时可能会T;

    法二:$O(n^2)$递推。法三:Dp。也是$O(n^2)$。

    法四:

    这里给出一种数学方法——卡特兰数。

    若有n个元素待出栈,那么所有可能的出栈方法有C(2n,n)-C(2n,n-1)种。(C为组合数)

    C(2n,n)-C(2n,n-1)为卡特兰数。其实卡特兰数有许多表示方法,这是最高效的一种。

    另外,它的递推式为h(n)=h(n-1)*(4*n-2)/(n+1)。

    多说一句,在一个凸多边形中,通过若干条互不相交的对角线,把这个多边形划分成了若干个三角形。凸多边形的边数n,求不同的方案数f(n),也为卡特兰数。

    然后再多说一句求组合数的方法。可以输出杨辉三角。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 using namespace std;
     5 int c[2002][2002];
     6 int n,fin;
     7 int main()
     8 {
     9     scanf("%d",&n);
    10     for(int i=1;i<=2*n;i++) c[i][1]=1,c[i][i]=1;
    11     for(int i=3;i<=2*n;i++)
    12     {
    13         for(int j=2;j<=i;j++)
    14         {
    15             c[i][j]=c[i-1][j-1]+c[i-1][j];
    16         }
    17     }
    18     fin=c[2*n][n]-c[2*n][n-1];
    19     printf("%d",fin);
    20     return 0;
    21 } 

    3)———单调栈

    Poj 2559

    求最大矩形的面积

    思考方法:先从简单情况入手,若矩形高度单调递增,可以把每个矩形的高度作为最终矩形的高度,把宽度扩展到右边界。若突然出现一个矮的,前面矩形的一部分就没有用了,可以直接报废,弹出栈顶元素直到栈首小于等于当前,再进栈。以维护序列的递增性。

    另外特判,防止最后还有多余矩形可以增加一个高度为0的矩形。

    时间复杂度为O(N)。

    单调栈的好处就在于及时排除不可能的选项,保持策略的高度有效秩序。--lyd

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 using namespace std;
     7 int n,p;
     8 long long ans;
     9 int a[100005];
    10 int s[100005];
    11 int w[100005];
    12 void sta(int n,int a[])
    13 {
    14     a[n+1]=0;
    15     for(int i=1;i<=n+1;i++)
    16     {
    17         if(a[i]>s[p])
    18         {
    19             s[++p]=a[i];
    20             w[p]=1;
    21         } 
    22         else 
    23         {
    24             int wid=0;
    25             while(s[p]>a[i])
    26             {
    27                 wid+=w[p];
    28                 ans=max(ans,(long long)s[p]*wid);    
    29                 p--;
    30             }
    31             s[++p]=a[i];
    32             w[p]=wid+1;
    33         }
    34     }
    35     cout<<ans<<endl;
    36 }
    37 int main()
    38 {
    39     while(1)
    40     {
    41         scanf("%d",&n);
    42         if(n==0) break;
    43         for(int i=1;i<=n;i++)
    44         scanf("%d",&a[i]);
    45         sta(n,a);
    46         memset(a,0,sizeof(a));
    47         memset(s,0,sizeof(s));
    48         memset(w,0,sizeof(w));
    49         ans=0,n=0;
    50     }
    51     return 0;
    52 }

    4)对顶栈的思想

    hdu4699

    有光标移动的编辑器。用两个栈存储,1~当前光标位置存在第一个栈中、剩下的存在另一个栈中。

    二、队列

  • 相关阅读:
    创业感悟:工程师的自我突破
    如何向Openstack社区提交一个新项目
    Advacned Puppet: Puppet Master性能调优
    Mysql Join语法解析与性能分析
    git初体验(七)多账户的使用
    (2):Mysql 查看、创建、更改 数据库和表
    博客索引
    双声道合并为单声道
    树莓派命令行配置无线网络
    树莓派安装Ubuntu系统
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/8806995.html
Copyright © 2011-2022 走看看