基础数据结构 ①(栈|队列|链表)

*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\n");
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\n");
43             return ;
44             }
45         }
46     }
47     if(res.top()<60)
48     {
49         printf("NO\n");
50         return ;
51     } 
52     printf("YES\n");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~当前光标位置存在第一个栈中、剩下的存在另一个栈中。

二、队列

 

posted @ 2018-04-12 12:12  cellur925&Chemist  阅读(179)  评论(0编辑  收藏  举报