Pop Sequence判断出栈序列是否合法

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    

这道题主要考察栈的知识,已知入栈序列,判断出栈序列是否合法。
第一行输入获取三个数字分别为栈的容量M,输入序列的元素数量N,输入序列的数量K。然后每一行都为一个出栈序列,如果输入序列有N个值,那么入栈序列为1,2,3,…,N。

规则是:出栈序列中的每个数后面的比它小的数,是按递减排列的。

简化规则描述:

1、假设入栈顺序为1234。

1)若出栈序列为4123,显然不满足上述要求,因为对于4,它后面比它小的数字序列为123,而123是一个递加系列即不是递减排列,所以不是合法出栈序列。

2)若出栈系列为3142,也不合法,因为3后面比它小的1和2不是递减排列的。

3)若出栈系列为1234,则合法,因为对于每一个数字它后面没有比它小的数字。

2、假设入栈顺序为123456789abcdef。

1)若出栈系列为67d51f94e2ba83c,因为对于d,它后面比它小的19或123或ac等等都不是递减的,所以不合法。

2)若出栈系列为379a8b65c4ed21f,可以证明是合法的出栈顺序。因为对于每一个数字它后面没有比它小的数字而且是按递减排列的。

3、证明:

假设入栈顺序为1234…n,可知在栈中的元素从栈顶到栈底一定是按严格递减排列的,而且每个数i进栈之前,比i小的数一定已经进栈了。

所以比i小的数要不然已经出栈,要不然在栈中,如果还在栈中则一定在i的下面,按严格递减排列,如此可见如果比i小的数还在栈中则一定在i之后输出,所以输出序列中在i后面的比i小的数一定按严格递减排列.否则出栈系列不合法。

思路:用一个辅助栈存储入栈序列,按出栈序列出栈,如果最后栈为空,则序列合法。

  1. 如果辅助栈不满,且入栈序列不空,入栈序列的下一个元素入栈
  2. 如果辅助栈的栈顶元素不等于出栈序列的首元素,一直入栈直到入栈序列为空
  3. 如果栈顶元素等于出栈序列的首元素,辅助栈顶元素出栈,指针移向出战序列的下一个元素
  4. 最后检查辅助栈是否为空,如果为空,说明出栈序列合法
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 1000

typedef struct SNode *Stack;
struct SNode{
	int Data[MaxSize];
	int Top;
}snode;


int Push(Stack S, int X){
	if (S->Top == MaxSize-1) {
		//printf("堆栈满\n");
		return 0;
	}
	S->Top++;
	S->Data[S->Top] = X;
	return 1;
}

int Pop(Stack S){
	if (S->Top == -1) {
		//printf("堆栈空\n");
		return 0;
	}
	else
		return (S->Data[(S->Top)--]);
}

int main(int argc, const char * argv[]) {
	
	int M, N, K;//栈的最大容量,单个序列元素个数,输入序列个数
	scanf("%d %d %d", &M, &N, &K);
	int i, j;
	Stack S;//辅助栈
	int v[N];
	for (i = 0; i<K; i++) {
		int current = 0;
		S = &snode;
		S->Top = -1;
		for (j = 0; j<N; j++) {
			scanf("%d", &v[j]);
		}
		for (j = 0; j<N; j++) {
			Push(S, j+1);
			//如果栈满还在入栈,说明此序列不合法
			if (S->Top+1 > M) {
				break;
			}
			//如果栈不为空并且栈顶元素和出栈序列相等,出栈
			while (S->Top!=-1 && S->Data[S->Top] == v[current]) {
				Pop(S);
				current++;
			}
		}
		//入栈与出栈数相等,说明此时栈为空,所有元素都访问过了,此序列合法
		if (p->Top == -1) {
			printf("YES\n");
		}
		else
			printf("NO\n");
	}
	
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值