關於棧結構的一個簡單練習是:給定入棧的字符序列,判斷當前序列能否由初始序列通過一系列的進棧出棧操作得到。下面通過展示兩道這種類型的題目來總結一下這種問題處理的思路。
在大方向上,我們應該都是通過基礎的棧的進棧出棧操作來模擬生成目標串的過程,判斷在過程中有沒有不合邏輯之處 。但是在具體實現上可以用多種寫法,比如可以以原串為主,也可以以當前串為主來進行循環。
第一題我用了鏈棧來實現。
問題 給定一個字符串,如s = "abc",通過逐個字符入棧和出棧可以得到另一個串。例如,'a'入棧,'b'入棧,再出棧,'c'入棧,再出棧,出棧,可以得到字符串"bca"。 但是,無論如何無法得到字符串"cab",因為若'c'先出棧,那么'a'和'b'必然都在棧中,而且當前棧頂為'b',因此無法得到"cab"。 給定一個串s,另外若干s的重組,請判斷哪些字符串可以通過棧重組得到。 測試輸入用例 第一行是一個正整數數n,第二行是一個字符串s,表示s的長度為n。 第三行是一個正整數m, 接下來是s的m個重組串,每個串占一行。 測試輸出用例 對於m個重組串中每個串t,每一行按照下列格式輸出t是否可以由s通過一個棧重組得到: s->t:k 其中k為1(表示可以通過棧重組得到)或者0(表示不可以通過棧重組得到) 輸入樣例 3 abc 3 abc bac cab 輸出樣例 abc->abc:1 abc->bac:1 abc->cab:0
用i,j兩個指針分別從頭掃描原串和當前串,對於當前串的當前位s1[j],欲使其出現在出棧序列中,就必須先將這一位字符壓進棧中。在原始串中尋找這個字符,那么在它之前出現的就必須全部依次被壓入棧中。掃描到原串的最后一位之后,就只能將棧里的所有剩余字符依次出棧。在這整個掃描過程中一旦判錯則直接返回0

1 /*len是串的長度,s0,s1分別為原串和當前串 */ 2 int OK(int len,char *s0,char *s1){ 3 int i,j;//i為指向原串s0,j為指向要判斷的串s1的箭頭 4 i=0;j=0; 5 Stack *S=(Stack*)malloc(sizeof(Stack));//不帶頭結點 6 //s0的最后一位進棧之前 7 while (i<len){ 8 if (s0[i]!=s1[j]){ 9 push(&S,s0[i]); 10 i++; 11 } 12 else{ 13 i++;j++; 14 while ((!isEmpty(S))&&S->c==s1[j]){//找到之后還不要忘了前面的是不是可以出棧 15 j++; 16 pop(&S); 17 } 18 } 19 if (j==len) return 1; 20 } 21 //s0的最后一位進棧之后,就只能倒着檢索直接判斷 22 while (j<len){ 23 if (s1[j]!=S->c) return 0; 24 pop(&S); 25 j++; 26 } 27 return 1; 28 }
另外一道題目的特點是對棧的大小做了限制,此題我用了數組來模擬棧,更方便統計棧內元素個數。
02-線性結構4 Pop Sequence (25分) (來源:PTA平台) Given a stack which can keep M numbers at most. Push N numbers in the order of 1, 2, 3, ..., N and pop randomly.
You are supposed to tell if a given sequence of numbers is a possible pop sequence of the stack. For example, if M is 5 and N is 7,
we can obtain 1, 2, 3, 4, 5, 6, 7 from the stack, but not 3, 2, 1, 7, 5, 6, 4. Input Specification: Each input file contains one test case. For each case, the first line contains 3 numbers (all no more than 1000):
M (the maximum capacity of the stack), N (the length of push sequence), and K (the number of pop sequences to be checked).
Then K lines follow, each contains a pop sequence of N numbers. All the numbers in a line are separated by a space. Output Specification: For each pop sequence, print in one line "YES" if it is indeed a possible pop sequence of the stack, or "NO" if not. Sample Input: 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 Sample Output: YES NO NO YES NO
如果說上一種寫法是從原串入棧的角度來把原串的指示變量作為循環的主要關注點,那么這道題目因為“原串”是一個默認的概念,不必專門存儲,就在循環過程中主要關注了“當前串”。但是兩種寫法的宗旨是不變的,都是利用棧來模擬儲存,關注過程中是否發生邏輯錯誤。

1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #define MAXSIZE 1020 5 #define MAXN 1020 6 7 bool OK(int n,int seq[],int size){ 8 int stack[MAXSIZE]; 9 memset(stack,0,sizeof(stack)); 10 bool In_stack[MAXN]; 11 memset(In_stack,0,sizeof(In_stack)); 12 int top=0; 13 for (int i=1;i<=n;i++){ 14 if (In_stack[seq[i]]){ 15 if (stack[top]!=seq[i]) return 0; 16 top--; 17 continue; 18 } 19 for (int j=1;j<=seq[i];j++){ 20 if (!In_stack[j]){ 21 stack[++top]=j; 22 In_stack[j]=1; 23 if (top>size) return 0; 24 } 25 } 26 top--;//當前出棧 27 } 28 return 1; 29 } 30 31 int main(){ 32 int Size,n,t; 33 int seq[MAXN]; 34 scanf("%d%d%d",&Size,&n,&t); 35 while (t){ 36 t--; 37 for (int i=1;i<=n;i++) scanf("%d",&seq[i]); 38 printf("%s",OK(n,seq,Size)?"YES":"NO"); 39 if (t) puts(""); 40 } 41 return 0; 42 }