输入入栈序列判断出栈序列是否合法(c语言实现)

题目:

分别给定入栈序列和出栈序列,然后判断出栈序列是否合法。如入栈序列是[6,5,4,3,2,1],出栈序列[4,5,3,1,2,6]是合法的,[3,4,6,5,2,1]是不合法的。


思路

判断出栈序列是否合法的标准是:栈顶如果是需要出栈的元素,则出栈,如果不是则将未入栈的元素按入栈序列依次入栈,直到栈顶为出栈的元素。如果所有元素都入栈了,仍然没有找到要弹出的元素,那么该出栈序列是不合法的。

创建一个临时数组存放入栈的元素,找到出栈序列第一个元素在入栈序列中的位置j,将j和j前面的元素加入临时数组中然后出栈序列中的元素依次与出栈序列j后面的元素和临时数组的栈顶元素进行判断如果与一分相同则消掉进行下一次判断.如果在入栈序列和临时数组都没有找到则在入栈序列中进行再次查找将找到的元素与j之间的元素加入临时数组中再重复上面的操作,如果没有找到则出栈序列是不合法的


 

一、运行实例

 

二、完整代码(详尽注释)

 

#include <stdio.h>  
#define maxn 50  
int out[maxn];//出栈序列
int one[maxn];//入栈序列
//打印出数组 入口参数依次为 要打印的数组 起始 结束
void debug(int* one,int i,int n)
{
	printf("\n打印出来为\n");
	for(i;i<=n;i++)
		printf("%d ",one[i]);
	printf("\n");
	
}
//入口参数依次为序列长度 入栈序列 出栈序列
int check(int n,int* one,int* out) 
{  
	int i,j,oot[50],top=-1,t=0;//i 用于循环 j代表入栈序列的下标 ott新建的临时数组 
	//top指向ott栈顶下标的变量等于-1时栈为空  t代表出栈序列的下标

	int m=0,j1,j2,cs=0;//当out[t]!=one[j]或out[t]!=ott[top]时加1如果一次循环中m=2则触发将入栈序列加入临时数组的语句
	//ji=j-1表示j在移动前的位置-1用于判断新的临时数组长度 j2=j1表示j在移动前的位置用来进行for循环 cs比较成功的次数

	//先找到和out第一个数据相同的one下标
	for(i=0;i<n;i++)
	{
		if(one[i]==out[0])
		{
			j=i;
			printf("第一个相同的下标为 %d\n",j);
			break;
		}
	}
	//将第一个下标之前的元素储存入oot数组
	for(i=0;i<=j;i++)
	{
		oot[i]=one[i];
	}
	top=j;//临时数组的最大下标为j
	j++;//入栈序列的下标跳过已经加入临时数组的数
	while(1)//使用break退出
	{
		printf("\n\n本次循环开始时j= %d t= %d top= %d \n\n ",j,t,top);
		m=0;//每次循环开始时清0 保证当m=2时是两个条件同时不满足的情况
		//你可能会问为什么不使用&& 那样会不知道是t++还是j++
		if((out[t]==oot[top]))
		{
			cs++;//使成功比较次数加1
			printf("%d.输出的 %d 将临时的数组 %d 换掉\n",cs,out[t],oot[top]);
			top=top-1;//将临时数组的最大下标减1
			t++;//将出栈序列的最大下标加1 进行下一次比较
			
		}
		else
		{
			m++;//不成功次数加1
		}
	
		if(out[t]==one[j])
		{
			cs++;
			printf("%d.输出的 %d 将输入 %d 换掉\n",cs,out[t],one[j]);
			j=j+1;//将入栈序列的最大下标加1
			t++;
				
		}
		else
		{
			m++;//不成功次数加1	
		}

		if(m==2)//当俩次都失败时
		{
			m=0;//清0
			j1=j-1;
			j2=j;
			debug(one,0,n-1);
			debug(out,0,n-1);
			for(i=j;i<n;i++)//找到与out[t]相同的下标 准备将它加入临时数组中
			{
				if(one[i]==out[t])
				{
					j=i;
					printf("相同的下标为 %d\n",j);
					break;
				}
				else
				{
					if(i<=n)//如果都没有找到与out[t]相同的下标则返回0
					{
						printf("未在剩下的序列里找到相同的数-错误\n");
						return 0;
					}
				}
			}
			if(top==-1)//如果为空则覆盖oot[0]
			{	
				for(i=0;i<=j-j1;i++,j2++)//将它加入临时数组中
				{
					oot[i]=one[j2];	
				}
				printf("top=%d j=%d j1=%d\n",top,j,j1);
				top=top+j-j1;
				printf("top_1=%d\n",top);
				debug(oot,0,top);
			}
			else//将它加入临时数组中
			{
				for(i=top+1;i<=j-j1;i++,j2++)
				{
					oot[i]=one[j2];
				}
				printf("top=%d j=%d j1=%d\n",top,j,j1);
				top=top+j-j1;
				printf("top_1=%d\n",top);
				debug(oot,0,top);
			}

		}
		else if(t>=n)//当t>=n时正常结束循环
			break;
	}
	return 1;//正常结束循环返回1

}  
int main()  
{  
    int n,k,i;
	//n代表入栈序列的长度 k代表运行的次数 i用于for循环
	printf("请输入入栈序列的长度和运行次数:");
	scanf("%d %d",&n,&k);
	printf("请输入进栈序列");
	for(i=0;i<n;i++)
	{  
		scanf("%d",&one[i]);
	}
	while(k--){

		printf("请输入出栈序列");
		for(i=0;i<n;i++)
		{  
			scanf("%d",&out[i]);

		}  
		if(check(n,one,out))  
			printf("YES\n");  
		else  
			printf("NO\n"); 	
	}
    return 0;  
}  

如果代码有bug,欢迎评论区留言指正。

  • 7
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值