《数据结构》浙大PAT 02-线性结构4 Pop Sequence
如何判断给定的序列符不符合要求主要看两点:
①序列的顺序是否满足栈后进先出的原则,不符合则NO。
②栈的最大容量有限制,达到上限时则NO。
实际编写代码时应该如何设计:
我的思路是:首先设计一个数组,将所给的序列存放到数组中。再设计一个堆栈,待入栈的元素为1。之后从头遍历数组:每一次遍历时数组元素都是当前待出栈的元素,比较待出栈与待入栈元素的大小,如果前者大于等于后者,依据后进先出的原则,入栈,直到后者大于等于前者(若超出栈的容量,则有问题)。之后开始出栈,将数组中的待出栈元素与实际出栈的值比较(如果不相等,则说明序列的顺序有问题),从而解决问题。
下面用文字来对三个实际序列进行分析,解释算法的实现过程:
①3 2 1 7 5 6 4
第一次循环开始时:待入栈元素为1,待出栈元素为3,不断入栈,直到待入栈元素为4,此时栈内元素为1,2,3。然后开始出栈,实际出栈元素为3,等于待出栈元素,第一次循环结束;第二次循环开始时:待入栈元素为4,待出栈元素为2,此时栈内元素为1,2。开始出栈,实际出栈元素为2,等于待出栈元素,第二次循环结束;第三次循环同上;第四次循环开始时:待入栈元素为4,待出栈元素为7,不断入栈,直到待入栈元素为8,此时栈内元素为4,5,6,7。开始出栈,实际出栈元素为7,等于待出栈元素,第四次循环结束;第五次循环开始时:待入栈元素为8,待出栈元素为5,此时栈内元素为4,5,6。开始出栈,实际出栈元素为6,不等于待出栈元素5,结束循环,指定序列顺序有误;
②7 6 5 4 3 2 1
第一次循环开始时:待入栈元素为1,待出栈元素为7,不断入栈,在入栈过程中超过栈的容量,指定序列有误。
③5 6 4 3 7 2 1
第一次循环开始时:待入栈元素为1,待出栈元素为5,不断入栈,直到待入栈元素为6,此时栈内元素为1,2,3,4,5。然后开始出栈,实际出栈元素为5,等于待出栈元素,第一次循环结束;第二次循环开始时:待入栈元素为6,待出栈元素为6,入栈,直到待入栈元素为7,此时栈内元素为1,2,3,4,6。开始出栈,实际出栈元素为6,等于待出栈元素,第二次循环结束;第三次循环开始时:待入栈元素为7,待出栈元素为4,此时栈内元素为1,2,3,4。开始出栈,实际出栈元素为4,等于待出栈元素,第三次循环结束;第四次循环开始时:待入栈元素为7,待出栈元素为3,此时栈内元素为1,2,3。开始出栈,实际出栈元素为3,等于待出栈元素,第四次循环结束;第五次循环开始时:待入栈元素为7,待出栈元素为7,入栈,直到待入栈元素为8,此时栈内元素为1,2,7。开始出栈,实际出栈元素为7,等于待出栈元素,第五次循环结束;第六次循环开始时:待入栈元素为8,待出栈元素为2,此时栈内元素为1,2。开始出栈,实际出栈元素为2,等于待出栈元素,第六次循环结束;第七次循环开始时:待入栈元素为8,待出栈元素为1,此时栈内元素为1。开始出栈,实际出栈元素为1,等于待出栈元素,最后一次循环结束,所给序列顺序正确。
下面给出C语言实现的完整代码:
#include <stdio.h>
#include <stdlib.h>
typedef struct StackNode *pNode;
struct StackNode
{
int data;
pNode next;
};
typedef struct StackNode *LinkStack;
void Push(LinkStack *S, int e);
int Pop(LinkStack *S);
int judge(int Maxsize, int N);
int main()
{
int M, N, K;
scanf("%d %d %d", &M, &N, &K);
int *jud = (int *)malloc(K * sizeof(int));
for (int i = 0; i < K; i++)
jud[i] = judge(M, N);
for (int i = 0; i < K; i++)
if (jud[i] == 0)
printf("NO\n");
else
printf("YES\n");
return 0;
}
void Push(LinkStack *S, int e)
{
pNode temp = (struct StackNode *)malloc(sizeof(struct StackNode));
temp->data = e;
temp->next = *S;
*S = temp;
}
int Pop(LinkStack *S)
{
int e = (*S)->data;
pNode temp = *S;
*S = (*S)->next;
free(temp);
return e;
}
int judge(int Maxsize, int N)
{
int *arr = (int *)malloc(N * sizeof(int));
for (int i = 0; i < N; i++) /*申请数组,用来存放一个需要判断的序列*/
{
scanf("%d", &arr[i]);
}
int p = 1;
int nowsize = 0;
int flag = 1;
LinkStack stack = NULL;
for (int i = 0; i < N; i++) /*该算法模拟实际的入栈出栈过程*/
{
while (arr[i] >= p) /*判断待出栈元素和未入栈元素的大小关系*/
{
if (nowsize == Maxsize)
break; /*栈满则退出*/
Push(&stack, p); /*如果前者更大,依据后进先出的原则,需要不断入栈,直到二者相等*/
nowsize++;
p++;
}
int temp = Pop(&stack); /*入栈结束后,开始出栈。*/
nowsize--;
if (arr[i] != temp) /*每次出栈的元素都应该等于待出栈元素,否则发生顺序错误。*/
flag = 0;
if (flag == 0)
break;
}
free(arr); /*将申请的空间全部释放*/
while (stack)
Pop(&stack);
return flag;
}