栈的压入、弹出序列 ----《剑指offer》面试题22

本文介绍了一种算法,用于判断给定的序列是否为一个栈的合法弹出序列。通过使用辅助栈并按照输入序列的顺序进行压入和弹出操作,可以验证序列的有效性。

题目

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

解题思路

  建立一个辅助栈,把输入的第一个序列中的数据依次压入该辅助栈,并按照第二个序列的顺序依次从该栈中弹出数字。
  如,压栈序列:1、2、3、4、5;弹出序列4、5、3、2、1;辅助栈为空;先判断辅助栈与弹出序列的栈顶元素是否相同,辅助栈为空,而pop序列的第一个元素是4,则从push序列中,取第一个入栈元素1,压入辅助栈。此时辅助栈中元素为:1; 继续判断与pop序列第一个元素是否相等,不等,又将push的2压入辅助栈中,直到辅助栈中压入4为止。此时,辅助栈中元素与pop栈顶元素4相等,辅助栈将4弹出,剩下:3、2、1;pop序列则移动到下一个元素5,继续从辅助栈中查找,没有,则继续将push栈中最后的一个元素5压入辅助栈中。push序列已经遍历完成。辅助栈中有:5、3、2、1; 其中5与pop栈顶元素相同,则辅助栈将5弹出,pop序列(用数组表示)又往后移动一位。继续比较省下的3、2、1等元素,直到在辅助栈中找到所有的元素,如果全部找到,则表示pop序列是push序列一个对应的出栈序列。否则,不是。

代码

#include <iostream>
#include <stack>
using  namespace std;

//  判断一个序列是否为栈的一个正确出栈序列
//  pPush:栈元素的入栈序列
//  pPop:栈元素的出栈序列
//  nLength: pPop的长度
bool IsPopOrder(const int* pPush, const int* pPop, int nLength)
{
    bool bPossible = false; //  结果

    if (pPush != nullptr && pPop != nullptr && nLength > 0)
    {
        const int* pNextPush = pPush;   //  pNextPush表示pPush移动的标记位
        const int* pNextPop = pPop;   //  pNextPop表示pPop移动的标记位

        //  辅助栈,用入压入pPush中的元素,弹出pPop的元素
        std::stack<int> stackData;

        //  当出栈序列遍历结束,退出循环
        while (pNextPop - pPop < nLength)
        {
            //  如果stackData栈顶元素与pPop栈顶元素不同,则往stackData中压入pPush中的元素
            while (stackData.empty() || stackData.top() != *pNextPop)
            {
                //  当pPush中的元素全部压入辅助栈(stackData)中,则退出循环
                if (pNextPush - pPush == nLength)
                    break;

                //  往辅助栈中压入pPush中的元素,并向后移动pPush
                stackData.push(*pNextPush);
                ++pNextPush;
            }

            //  如果在不断的压栈的过程中,未能找到入pPop栈顶相匹配的元素,则pPop不是一个正确的出栈序列
            if (stackData.top() != *pNextPop)
                break;

            //  如果辅助栈中的栈顶元素与pPop栈顶元素相同,则stackData弹出元素,pNextPop后移
            stackData.pop();
            ++pNextPop;
        }

        //  如果辅助栈中所有元素都已弹出,且出栈序列中所有元素都已经出栈,则返回成功
        if (stackData.empty() && pNextPop - pPop == nLength)
            bPossible = true;
    }

    return bPossible;
}



int main()
{
    int push[] = {1,2,3,4,5,6,7};
    int pop_1[] = {4,5,3,6,2,7,1};
    int pop_2[] = {7,6,4,5,3,2,1};
    cout << "pop_1 is " << IsPopOrder(push, pop_1, 7) << endl;
    cout << "pop_2 is " << IsPopOrder(push, pop_2, 7) << endl;

    return EXIT_SUCCESS;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值