二叉树遍历_前序中序确定其后序(C++)

前言:

  说到二叉树,我之前写过一篇博客,讲的就是二叉树的遍历,但是为什么再讲一遍呢?

  当然,因为不同。这也解决了我之前关于树的一个疑惑。我当时建树的时候是前序建树,只有前序遍历的结果,并不能唯一的确定一棵二叉树,因而我采用了类似 a b null null c null null 的形式来确定化其树的形态,而一旦知道了中序遍历还有(前序遍历和后序遍历)的任何一个,就可以确定其二叉树形态,因而就只写序列就可以了,而不需要再用null。

问题:

  知道一棵二叉树的前序遍历和中序遍历求其后序遍历。

  输入:

  ABC
  BAC


  FDXEAG
  XDEFAG

原理:

  首先前序遍历(根左右)的第一个元素肯定是根节点,那么通过寻找中序遍历(左根右)中根节点的位置,就可以把

中序序列分为左右子树,假设其长度为l和r,那么其前序遍历的序列长度可以表示为:1+l+r ,分别代表根,左子树,右子树。

同理,分别对左右子树进行同等操作,就可以确定二叉树的形态。

当然,后序遍历和中序遍历也适用。

Ok,let‘s see the code now !

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>


//二叉树遍历。
//前序+中序确定一棵树。
//同理:后序+中序确定一棵树。
/*
思想:
前序和后序能确定根节点的位置,
通过查找中序遍历根节点的位置,可以确定其左右子树,
对其左右子树进行同样的操作,递归即得二叉树的形态。
*/


using namespace std;

string sPre,sIn;//前序遍历和中序遍历的字符串。


struct node{
    char weight;
    node* lChild;
    node* rChild;
};

node* buildTree(int s1,int e1,int s2,int e2)
{
    node* root=new node({sPre[s1],NULL,NULL});
    int rootId;
    for(int i=s2;i<=e2;i++)//寻找中序遍历root结点的位置
    {
        if(sIn[i]==sPre[s1])
            {
                rootId=i;
                break;
            }
    }

    if(rootId!=s2)//如果中序遍历的根节点前面有结点肯定是其左子树,其结点个数为rootId-s2
    {
        root->lChild=buildTree(s1+1,s1+rootId-s2,s2,rootId-1);
    }
    if(rootId!=e2)//同理,中序遍历根节点后面有结点肯定是其右子树,结点数为e2-rootId
    {
        root->rChild=buildTree(e1-e2+rootId+1,e1,rootId+1,e2);
    }
    return root;

}



void postOrder(node* root)
{
    if(root->lChild!=NULL)
        postOrder(root->lChild);
    if(root->rChild!=NULL)
        postOrder(root->rChild);
    cout<<root->weight;
}



int main()
{

    while(cin>>sPre>>sIn)
    {

        node*root=buildTree(0,sPre.length()-1,0,sIn.length()-1);
        postOrder(root);
        cout<<endl<<endl;
    }


    return 0;
}

结果:

总结:

本身题目并不难,但是解决了自己的一个疑问,很值!

猜你喜欢

转载自blog.csdn.net/Look_star/article/details/99201701