堆栈模拟/pta_02_线性结构4_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.

给定一个最多可以保存M个数字的堆栈。按1、2、3、…的顺序按N个数字, N和随机弹出。您应该知道给定的数字序列是否可能是堆栈的弹出序列。例如,如果M是5,N是7,我们可以从堆栈中得到1,2,3,4,5,6,7,而不是3,2,1,7,5,6,4。

输入样式

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.

每个输入文件包含一个测试用例。对于每种情况,第一行包含3个数字(都不超过1000):M(堆栈的最大容量)、N (push序列的长度)和K(要检查的pop序列的数量)。然后接着K行,每一行包含一个由N个数字组成的弹出序列。一行中的所有数字用一个空格隔开。

输出样式
For each pop sequence, print in one line “YES” if it is indeed a possible pop sequence of the stack, or "NO" if not.

对于每个弹出序列,如果它确实是一个可能的堆栈弹出序列,则打印一行“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

代码如下,写的有点勉强,其实上面的题目的意思就是给定一串字符串,让你来判断通过1-n的数字是否能够在堆栈中通过压入弹出,最终获得题目给出的字符串,如果可以的话,那么就输出"Yes",不可以就输出"No"

#define _CRT_SECURE_NO_WARNINGS
#define MAXSIZE 1001
#define STACKSIZE 10
#include<stdio.h>
#include<stdlib.h>

int main() {
	int m, n, k; // m最大堆栈容量 n序列长度 k序列的总数量 , m=5 n=7 k=5

	scanf("%d %d %d", &m, &n, &k);

	// 总共存在几组序列,就遍历这几组序列
	for (int i = 0; i < k; i++)
	{
		int inputBuffer[MAXSIZE] = { 0 };
		int stackArray[MAXSIZE] = { 0 }; // 模拟栈结构
		int Array[MAXSIZE] = { 0 };  // 默认顺序存储 1-n 的数
		int resArray[MAXSIZE] = { 0 }; // 存放每组序列最终出栈完存储的值

		// initArr
		for (int initIndex = 0; initIndex < n; initIndex++)
			Array[initIndex] = initIndex + 1;

		int currentArrayLength = 0; // 作为栈顶的索引计数器
		for (int j = 0; j < n; j++)
		{
			scanf("%d", &inputBuffer[j]);
			if (j < n - m && inputBuffer[j] > n - 1)
			{
				// 特殊情况的处理,如果每次序列组中的第j个值是直接大于堆栈容量大小+j的话,那么这输入的序列的情况是不存在的
				// 剩余在缓冲区的字符还需要进行处理
				char ch; while ((ch = getchar()) != '\n' && ch != EOF);
				break;
			}

			if (inputBuffer[j] > m + j)
			{
				// 特殊情况的处理,如果每次序列组中的第j个值是直接大于堆栈容量大小+j的话,那么这输入的序列的情况是不存在的
				// 剩余在缓冲区的字符还需要进行处理
				char ch; while ((ch = getchar()) != '\n' && ch != EOF);
				break;
			}

			// 接下来就是正常的情况处理
			// 孙总的BUG: 3 2 1 5 7 4 6
			int currentArrayIndex = 0;
			int flag = 0;
			for (int p = 0; p < n - j; p++)
			{
				// 模拟压栈, 这里的currentArrayLength相当于栈顶的指针
				// 如果遍历的时候每次都不等于 Data[p] 的话,那么都先压入到栈中
				// 不等于的时候有两种情况:
				// 1. inputBuffer[j] 比当前currentArrayLength指向的大
				// 2. inputBuffer[j] 比当前currentArrayLength指向的小
				if (Array[currentArrayLength] != inputBuffer[j]) // && stackArr[currentArrayIndex] != Data[j]
				{
					// 当inputBuffer[j] 比当前currentArrayLength指向的小的时候,这时候也有两种情况
					// 2.1 inputBuffer[j] - stackArray[currentArrayLength-1] = 1 
					// 2.2 inputBuffer[j] - stackArray[currentArrayLength-1] > 1 
					if (stackArray[currentArrayLength - 1] == inputBuffer[j])
					{
						// 模拟出栈操作,首先stackArray中currentArrayLength所指向的得出来
						resArray[j] = stackArray[currentArrayLength - 1];
						// 然后还需要清空当前的currentArrayLength为0
						stackArray[currentArrayLength - 1] = 0;
						//currentArrayLength--; // 每次入栈/入栈,当前栈顶的位置currentArrayLength都需要发生变动
						for (int currentPosition = currentArrayLength - 1; currentPosition < n; currentPosition++)
						{
							Array[currentPosition] = Array[currentPosition + 1];
						}
						currentArrayLength--;
						break;
					}

					// 如果要入栈,此时在入栈之前还需要判断下当前堆栈的容量是否充足
					// 这里在 压栈之前判断最后一个压入的元素的索引值 是否等同于 当前堆栈的容量大小
					
					/*
					int countNum = 0;
					while (*(stackArray+countNum))
					{
						countNum++;
						if (countNum == m)
						{
							flag = 1;
							break;
						}
					}
					if (flag == 1)
						break;
					*/
					// inputBuffer[j] 比当前currentArrayLength指向的大
					// 3 2 1 5 7 4 6
					// 并且此时堆栈容量还足够,所以可以进行压入操作
					
					/*
					int flag2 = 0;
					for (int o = 0; o < currentArrayLength+1; o++)
					{
						if (stackArray[o] == Array[o])
							continue;
						else
						{
							stackArray[o] = Array[o];
							currentArrayIndex++;
							currentArrayLength++; // 每次入栈/入栈,当前栈顶的位置currentArrayLength都需要发生变动
							flag2 = 1;
							break;
						}
					}
					if (flag2)
						break;
						*/

					/*
					while (stackArray[tmp] == Array[tmp])
					{
						// int tmp = currentArrayIndex;
						tmp++;
						// stackArray[tmp] = Array[tmp];
						// currentArrayIndex++;
						// currentArrayLength++;
					}*/

					/*
					int tmp = currentArrayIndex;
					if (stackArray[tmp] == Array[tmp])
					{
						int tmp = currentArrayIndex;
						tmp++;
						stackArray[tmp] = Array[tmp];
						currentArrayIndex++;
						currentArrayLength++;
						continue;
					}
					*/
					
					// inputBuffer[j] 比当前currentArrayLength指向的大
					// 并且此时堆栈容量还足够,所以可以进行压入操作
					stackArray[currentArrayLength] = Array[currentArrayLength];
					currentArrayIndex++;
					currentArrayLength++; // 每次入栈/入栈,当前栈顶的位置currentArrayLength都需要发生变动
				}
				else if (stackArray[currentArrayLength] == inputBuffer[j])
				{
					resArray[j] = inputBuffer[j];
					// 修正
					stackArray[currentArrayLength] = 0;
				}
				else{
					// 如果栈顶的值等于所需要的序列[j]的值,那么此时就模拟出栈操作,并且修正位置
					resArray[j] = Array[currentArrayLength];
					//currentArrayLength--; // 每次入栈/入栈,当前栈顶的位置currentArrayLength都需要发生变动
					for (int currentPosition = currentArrayLength; currentPosition < n; currentPosition++)
					{
						Array[currentPosition] = Array[currentPosition + 1];
					}
					break;
				}
			}

			if (flag == 1)
				break;
		}
		// 最终进行序列判断
		for (int count = 0; count < n; count++)
		{
			if (resArray[count] != inputBuffer[count])
			{
				printf("NO\n");
				break;
			}

			if (count == (n - 1))
			{
				printf("YES\n");
				break;
			}
		}
	}
	return 0;
}

上个图

posted @ 2021-10-20 23:37  zpchcbd  阅读(105)  评论(0)    收藏  举报