栈 入栈序列与出栈序列 合法性 的一个有趣问题

4.输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。 假设压入栈的所有数字均不想等。 
例如: 序列 1 2 3 4 5 是某栈的压栈序列, 序列 4 5 3 2 1是该压栈序列对应的一个弹出序列, 但 4 3 5 1 2就不可能是该压栈序列的弹出序列。


思路: 首先我们来 理解下题意, 有些人可能会这么想, 1 2 3 4 5为压栈序列, 弹出序列一定是 5 4 3 2 1 啊
4 5 3 2 1 一定不是它的一个弹出序列。  并不是这样的 , 我们来分析 , 如果我们 压入 123 Pop 一次 再压入 4 5
此时全部Pop 则, 压入序列为 1 2 3 4 5 弹出序列为 3 5 4 2 1


理清了题意, 我们此时进行分析.   先给一串 简单 入栈出栈序列
入栈: 1 2 3 4 5
出栈: 3 5 4 2 1
我们首先来看弹出序列, 弹出序列的第一个元素为3, 则弹出3时,3必须在栈顶。 入栈 -->1 -->2 -->3, 直到要弹出元素与栈顶元素相等(此时为3), 弹出。
接下来要弹出元素为 5, 和栈顶元素(2)不相等, 即继续入栈, 直到遇到元素 5. 入栈 -->4 -->5. 弹出5。 接下来, 栈顶元素为4 , 要弹出元素为4, 弹出。
重复上述过程,    最后,如果入栈序列已经为空, 但 栈顶 依旧和 弹出序列元素 不相等, 则他们不匹配。 如果 两者都 为空, 则它们匹配。


题目条件:  所有数字均不相等。   --->   保证了以上想法的正确性。
为了更好的验证我们的想法, 判断这个问题, 我们使用一个辅助栈。

我们使用 两种方法 来 实现 并进行测试


#include <stack>
#include <iostream>
#include <windows.h>
using namespace std;


//我们就不考虑那种, 入栈序列 和 出栈序列 元素个数不相等的问题了, 假设他们相等, 长度皆为length.
//因为它们的长度相同, 我们仅通过 length 来判断 入栈序列是否已经结束(防止数组越界)。  出栈序列我们不关心它走到尽头,
//因为我们的代码实现中, 保证了出栈序列数组不会越界。
bool IsPopOrder1( const int* pPush, const int* pPop, int length )
{
	stack<int> s;

	while ( 0 != length || 0 != s.size( ) )
	{
		//分两种情况:
		//第一种 入栈序列还有元素
		if ( 0 != length )
		{
			if ( 0 != s.size( ) )
			{
				if ( *pPop == s.top( ) )			//注意, 可以 s.push( *push++ )  因为 push后, pPush是一定要++的。 但 *pPop++ == s.top( )  就是错的了。 因为 只有相等才会 执行 s.pop( ) 接着才会 ++pPop.  而不是每次验证后都++  --->  *pPop++(即加加的是指针,而不是值)
				{
					s.pop( );
					++pPop;
				}
				else
				{
					while ( 0 != length && *pPop != s.top( ) )
					{
						s.push( *pPush++ );
						--length;
					}

					if ( 0 == length && *pPop != s.top( ) )
						return false;

					s.pop( );
					++pPop;
				}
			}
			else
			{
				//这样写是错的,  栈为空 ,怎么用 *pPop != s.top( )这个条件, 所以  do while 循环
				//while ( 0 != length && *pPop != s.top( ) )
				//{
				//	s.push( *pPush++ );
				//
				//	--length;
				//}

				do {
					s.push( *pPush++ );
					--length;
				} while ( 0 != length && *pPop != s.top( ) );

				if ( 0 == length && *pPop != s.top( ) )
					return false;

				//运行到这里, 则,不管是 length 等不等于0。 *pPop == s.top( ) 这个条件一定是成立的!
				s.pop( );
				pPop++;
			}
		}
		else
		{
			//第二种: 入栈序列已经 没有元素 了
			if ( *pPop == s.top( ) )
			{
				s.pop( );
				++pPop;
			}
			else
				return false;
		}
	}

	return true;
}

bool IsPopOrder2( const int* pPush, const int* pPop, int nLength )//如果 不用 bPossible 这个变量, 则代码如下所示, 程序会少执行几步代码, 不过 "或许 牺牲"  了 代码的 可读性, 与 简明性.
{
	//bool bPossible = false;
	if ( NULL != pPush && NULL != pPop && nLength > 0 )
	{
		const int* pNextPush = pPush;
		const int* pNextPop = pPop;

		stack<int> stackData;

		while ( pNextPop - pPop < nLength )
		{
			while ( stackData.empty( ) || *pNextPop != stackData.top( ) )
			{
				if ( pNextPush - pPush == nLength )
					//break;
						return false;

				stackData.push( *pNextPush );
				++pNextPush;
			}
			//if ( *pNextPop != stackData.top( ) )
			//	break;

			stackData.pop( );
			++pNextPop;
		}
		//if ( stackData.empty( ) && nLength == pNextPop - pPop )
		//	bPossible = true;
		return true;
	}
	//return bPossible;
}

void Test( )
{
	int push[] = { 1, 2, 3, 4, 5 };
	int pop1[] = { 3, 5, 4, 2, 1 };				//true
	int pop2[] = { 3, 5, 4, 1, 2 };				//false

	int length = sizeof( push ) / sizeof( push[0] );

	cout << "1 :\n";
	cout << IsPopOrder1( push, pop1, length ) << endl;
	cout << IsPopOrder1( push, pop2, length ) << endl << endl;

	cout << "2 :\n";
	cout << IsPopOrder2( push, pop1, length ) << endl;
	cout << IsPopOrder2( push, pop2, length ) << endl;
}

int main( )
{
	Test( );

	system( "pause" );
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值