【算法】栈的压入、弹出序列,从上到下打印二叉树

版权声明:本文为博主原创学习笔记,如需转载请注明来源。 https://blog.csdn.net/SHU15121856/article/details/82561219

面试题31:栈的压入、弹出序列

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

用一个栈模拟一下压入和弹出的过程,两个序列不同步地向前走,当压入后栈顶出现要弹出的元素时就弹出,否则就继续压入。

#include<bits/stdc++.h>
using namespace std;

// 参数:
//        pPush:       压栈序列
//        pPop:        出栈序列
//        nLength:     序列的长度
// 返回值:
//        这两个序列能否匹配
//const位于*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量
//如果const位于*的右侧,const就是修饰指针本身,即指针本身是常量
bool IsPopOrder(const int* pPush, const int* pPop, int nLength) {
    bool bPossible = false;//初始:不能匹配
    //输入合法性检查
    if(pPush != nullptr && pPop != nullptr && nLength > 0) {
        //定义两个用来移动的指针,保留之前的指针用来比较
        const int* pNextPush = pPush;
        const int* pNextPop = pPop;

        std::stack<int> stackData;//用一个STL栈来模拟

        //只要没有移动出序列(这两个序列一样长),就要继续判断
        while(pNextPop - pPop < nLength) {
            //栈为空,或者栈内的栈顶元素不是要弹出的元素
            while(stackData.empty() || stackData.top() != *pNextPop) {
                //压栈之前先检查一下,如果所有数字都压入辅助栈了,退出循环
                if(pNextPush - pPush == nLength)
                    break;
                //压栈
                stackData.push(*pNextPush);
                //压栈以后,压栈序列的指针要向后走,表示一个元素已经压过栈了
                pNextPush ++;
            }

            //至此,栈内的栈顶元素可能是要弹出的元素
            //还有一种可能就是所有数字都压入辅助栈了

            //总之需要再判断一下栈顶元素是不是弹出序列中要弹出的元素
            if(stackData.top() != *pNextPop)//如果不是
                break;//失败退出

            //至此,一定能正常弹出
            stackData.pop();
            pNextPop ++;//弹出序列向前走,下个循环继续判断
        }

        //循环结束后,通过判断栈内是否清空且弹出序列走完
        if(stackData.empty() && pNextPop - pPop == nLength)
            bPossible = true;//就能知道是否成功匹配了
    }

    return bPossible;
}

int main() {
    const int nLength = 5;
    int push[nLength] = {1, 2, 3, 4, 5};
    int pop[nLength] = {3, 5, 4, 2, 1};
    cout<<boolalpha<<IsPopOrder(push,pop,nLength);
    return 0;
}

面试题32:从上到下打印二叉树

就是层序遍历二叉树,用队列。初始时候树根入队,循环中每次将队头取出来输出,然后将其左右孩子入队,直至队空。本质是广度优先遍历有向图。

#include<bits/stdc++.h>
#include "..\Utilities\BinaryTree.h"
using namespace std;

//输入二叉树根结点,输出从这里开始的其层序遍历结果
void PrintFromTopToBottom(BinaryTreeNode* pRoot) {
    if(pRoot == nullptr)//输入非空校验
        return;

    //使用STL的deque(双端队列),其实只要是普通的队列就够了
    deque<BinaryTreeNode *> dequeTreeNode;

    dequeTreeNode.push_back(pRoot);//根节点从后入队

    //只要队列非空,就一直做
    while(dequeTreeNode.size()) {
        //取队头
        BinaryTreeNode *pNode = dequeTreeNode.front();
        dequeTreeNode.pop_front();
        //将其输出
        printf("%d ", pNode->m_nValue);
        //非空左孩子从后入队
        if(pNode->m_pLeft)
            dequeTreeNode.push_back(pNode->m_pLeft);
        //非空右孩子从后入队
        if(pNode->m_pRight)
            dequeTreeNode.push_back(pNode->m_pRight);
    }
}

//            10
//         /      \
//        6        14
//       /\        /\
//      4  8     12  16
int main() {
    BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10);
    BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6);
    BinaryTreeNode* pNode14 = CreateBinaryTreeNode(14);
    BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
    BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8);
    BinaryTreeNode* pNode12 = CreateBinaryTreeNode(12);
    BinaryTreeNode* pNode16 = CreateBinaryTreeNode(16);

    ConnectTreeNodes(pNode10, pNode6, pNode14);
    ConnectTreeNodes(pNode6, pNode4, pNode8);
    ConnectTreeNodes(pNode14, pNode12, pNode16);

    PrintFromTopToBottom(pNode10);

    DestroyTree(pNode10);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/SHU15121856/article/details/82561219