第三章 实践2 学习心得(顺序栈+数组)

题目及sample如下:

7-1 出栈序列的合法性 (20分)
 

给定一个最大容量为 M 的堆栈,将 N 个数字按 1, 2, 3, ..., N 的顺序入栈,允许按任何顺序出栈,则哪些数字序列是不可能得到的?例如给定 M=5、N=7,则我们有可能得到{ 1, 2, 3, 4, 5, 6, 7 },但不可能得到

{ 3, 2, 1, 7, 5, 6, 4 }。

输入格式:

输入第一行给出 3 个不超过 1000 的正整数:M(堆栈最大容量)、N(入栈元素个数)、K(待检查的出栈序列个数)。最后 K 行,每行给出 N 个数字的出栈序列。所有同行数字以空格间隔。

输出格式:

对每一行出栈序列,如果其的确是有可能得到的合法序列,就在一行中输出YES,否则输出NO

输入样例:

5 7 5
1 2 3 4 5 6 7
3 2 1 7 5 6 4
7 6 5 4 3 2 1
5 6 4 3 7 2 1
1 7 6 5 4 3 2
 

输出样例:

YES
NO
NO
YES
NO

先总结一下自己在第一遍敲代码时的错,一开始的思路是:按顺序将元素入栈,直至栈满。把栈顶元素跟需要检验的出栈序列相比较,如果相等,则出栈。最后检验是否栈空,如果是,就输出YES,否则输出NO。错误代码不堪入目就不贴上来啦。之所以做错的原因是:搞不清楚入栈和把栈顶数字做比较那一块要怎么做。一开始觉得这两个操作应该有个时间差,得先入栈完才能比较;但是栈的容量不够,根本没办法入栈完。然后就一边入栈一边比较,但是这样的话自己思路全乱了,嵌套了4、5个循环。

后来看了别人的博客上AC的代码,边看边敲,写了详细的注释,AC代码如下:

#include <iostream>
#include <bits/stdc++.h> //包含 stack<int> 的头文件
using namespace std ;
stack<int> s ;
 
int main()
{
     int m, n, k ;
     cin >> m >> n >> k ;
     //m: 堆栈最大容量 ; n: 入栈元素个数 ; k: 待检查的出栈序列个数
 
     int a[1005] ; //保险起见,将数组容量定义到1005
     int t1, t2 ;
 
     while(k--)
     {
          //每次循环重新开始时,如果栈非空,需要先清空栈!!
          while(!s.empty()) 
         {
             s.pop() ;
         }
  
          t1 = 1 ; //t1: 可以理解为压入栈的数字(1,2,3,4...,n)
          t2 = 1 ; //t2: 可以理解为到数组的第几个位置(下标加1)
  
          for(int i=1 ; i<=n ; i++)
          {//输入 需要检验的出栈序列
               cin >> a[i] ;
          }
  
          int flag = 1 ; //用于判断一种错误的特殊情况,此情况下出错栈非空,无法用s.empty()判断
  
          while(1)
          {
               if(t1 == a[t2])
              {
                    t1++ ;
                    t2++ ;
              }
              else if(!s.empty() && s.top() == a[t2])
             { //条件:栈非空、栈顶数字与出栈序列当前的数字相等,
               //结果:出栈,且t2++,出栈序列往后挪一位继续检查
                    s.pop() ;
                    t2++ ;
              }
              else
              { //这里判断两种特殊情况:
                /*1)如果应该压入栈的数字已经大于n,说明1到n的数字全都经过了检验,此时循环可以停止
                   2)如果栈的长度大于规定好的容量m,说明出栈序列是错的,flag变为0,停止循环
                   例如:m=5,而出栈序列为 6,5,4... 则错误*/
                       if(t1 > n)   break ;
    
                       s.push(t1) ;
                       t1++ ;
    
                       if(s.size() >= m)
                      {
                          flag = 0 ;
                          break ;
                       }
              }
       }
             if(!flag || !s.empty())
             {
                      cout << "NO" << endl ;
             }
             else cout << "YES" << endl ;
     }
     return 0 ;
}

AC的代码里简化了需要入栈的情况,使用t1辅助比较,不需要每种情况都入栈。

然后学习了同组的珊珊的AC代码,她是用数组的做法。思路都是一样的,不过把栈变成数组stack[1007],将出、入栈变成数组下标的变化。

 

posted @ 2020-05-05 14:29  咕咕鸽子王  阅读(593)  评论(0编辑  收藏  举报