leetcode105 && leetcode106 && PAT 1138. 二叉树的三种遍历的应用

俗话说的好“你先前跳过的坑,迟早都要再踩进去的”
昨天考的PAT的利用二叉树的前序和中序遍历得到后序遍历的第一个值。想起在leetcode上做过,却没做出来。特此,对二叉树的三种遍历做个复习。

二叉树的三种遍历分别为:前序遍历(preorder),中序遍历(inorder),后序遍历(postorder),这三种遍历的区别直接体现在代码上,看如下三个代码:

void preorder(TreeNode* root)
{
    printNode(root);
    preorder(root->left);
    preorder(root->right);
}
void inorder(TreeNode* root)
{
    inorder(root->left);
    printNode(root);
    inorder(root->right);
}
void postorder(TreeNode* root)
{
    postorder(root->left);
    postorder(root->right);
    printNode(root);
}

以上就是三种遍历方式的代码,代码就是纯递归。只是输出的不同。那么,再来看下面的实例:
这里写图片描述

那么前序遍历(preorder)为:ABDCEGFHI
中序遍历(inorder)为:BDAGECHFI
后序遍历(postorder)为:DBGEHIFCA
大家可以根据上面的代码,自己推断一下遍历的结果。
从这些遍历的结果可以看到以下几个特点:
1.遍历的优先级左边优先.
2.前序遍历不断递归左边的点(将遇到的点入栈).
3.递归到底了,返回上面一层到右边(出栈),发生转变的时候,前序遍历的值会刚好等于中序遍历的值.
4.后序遍历刚刚看起来好像没什么规律。但是将后序遍历反转一下呢?得到如下的结果:ACFIHEGBD。再观察一下树,没错了,反转之后得到的结果是树的优先向右遍历的结果。但是什么时候判断到底,也就是什么时候判断要转向了呢?我们也照反转的方式,将中序遍历反转,得到结果:IFHCEGADB。哈哈,没错这是当反转的后序等于反转的中序的时候就说明到底了,需要转向了。

知道了上面四点性质,下面这三道题就很简单了:
leetcode105:
利用前序遍历和后序遍历构建树。
根据性质1,2,3
建立一个栈,遍历前序向栈压结点。直到和中序遍历的值相等,说明到底,出栈,转向。
代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if(preorder.empty() || inorder.empty()) return NULL;
        stack<TreeNode*> stree;
        int size=inorder.size();
        int i=1;
        int j=0;
        int flag=0;     //向右进行的标志
        TreeNode* node=new TreeNode(preorder[0]);
        TreeNode* root=node;
        if(preorder.size()==1) return root;
        stree.push(node);
        while(i<size)
        {
            //表示应该转向了
            if(!stree.empty() && ((stree.top())->val==inorder[j]))
            {
                node=stree.top();
                stree.pop();
                flag=1;
                j++;
            }
            else
            {
                TreeNode* tmp=new TreeNode(preorder[i]);
                i++;
                if(flag==0)
                {
                    node->left=tmp;
                    node=node->left;
                    stree.push(tmp);
                }
                else
                {
                    node->right=tmp;
                    node=node->right;
                    stree.push(tmp);
                    flag=0;
                }
            }
        }
        return root;
    }
};

106.利用后序遍历和中序遍历还原树
根据性质四.将中序遍历和后序遍历的结果反转,将右的优先级调整高于左,和上面一样的思路。
代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
    if(inorder.empty()) return NULL;
    stack<TreeNode *>st;
    reverse(inorder.begin(),inorder.end());
    reverse(postorder.begin(),postorder.end());
    TreeNode* root=new TreeNode(postorder[0]);
    TreeNode* node=root;
    st.push(node);
    int i=1; int j=0; int flag=0;   //0说明向右
    int size=postorder.size();
    while(i<size)
    {
        if(!st.empty() && (st.top()->val)==inorder[j])
        {
            node=st.top();
            st.pop();
            j++;
            flag=1;      //1说明转向,转向到左
        }
        else
        {
            TreeNode *temp=new TreeNode(postorder[i]);
            if(flag==0)
            {
                node->right=temp;
                node=node->right;
            }
            else
            {
                flag=0;
                node->left=temp;
                node=node->left;
            }
            st.push(temp);
            i++;
        }
    }
    return root;

    }
};

PAT 1138.给出前序和中序遍历,给出后序的第一个值。这个,不多说了
代码:

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

struct TreeNode{
    int value;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x):value(x),left(NULL),right(NULL) {}
};


int a[50001];
int b[50001];
int flag3=0;

void postorder(TreeNode* a);

int main()
{
    int n;
    cin>>n;

    for(int i=0;i<n;++i)
    {
        cin>>a[i];
    }    
    for(int i=0;i<n;++i)
    {
        cin>>b[i];
    }
    if(n==1)
    {
        cout<<a[0];
    }
    int flag=0;
    int i=1;
    int j=0;
    stack<TreeNode *>st;
    TreeNode* root=new TreeNode(a[0]);
    TreeNode* node=root;

    st.push(root);
    while(i<n)
    {
        //转向
        if(!st.empty() && (st.top())->value==b[j])
        {
            node=st.top();
            st.pop();
            flag=1;
            j++;
        }
        else
        {
            TreeNode* tmp=new TreeNode(a[i]);
            i++;
            if(flag==0)
            {
                node->left=tmp;
                node=node->left;
                st.push(node);
            }
            else
            {
                node->right=tmp;
                node=node->right;
                st.push(node);
                flag=0;
            }
        }
    }

    postorder(root);


}


void postorder(TreeNode* a)
{
    if(flag3==1 || a==NULL)
    {
        return;
    }
    else
    {
        postorder(a->left);
        postorder(a->right);
        if(flag3==0)
        {
            cout<<(a->value);
            flag3=1;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值