二叉樹遍歷_前序中序確定其後序(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;
}

結果:

總結:

本身題目並不難,但是解決了自己的一個疑問,很值!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章