天天看點

已知二叉樹的中序和前序(或者後序)序列求解樹

這種題一般有二種形式,共同點是都已知中序序列。如果沒有中序序列,是無法唯一确定一棵樹的,證明略。

一、已知二叉樹的前序序列和中序序列,求解樹。  相關題目

1、确定樹的根節點。樹根是目前樹中所有元素在前序周遊中最先出現的元素。

2、求解樹的子樹。找出根節點在中序周遊中的位置,根左邊的所有元素就是左子樹,根右邊的所有元素就是右子樹。若根節點左邊或右邊為空,則該方向子樹為空;若根節點左邊和右邊都為空,則根節點已經為葉子節點。

3、遞歸求解樹。将左子樹和右子樹分别看成一棵二叉樹,重複1、2、3步,直到所有的節點完成定位。

二、已知二叉樹的後序序列和中序序列,求解樹。

1、确定樹的根。樹根是目前樹中所有元素在後序周遊中最後出現的元素。

2、求解樹的子樹。找出根節點在中序周遊中的位置,根左邊的所有元素就是左子樹,根右邊的所有元素就是右子樹。若根節點左邊或右邊為空,則該方向子樹為空;若根節點左邊和右邊都為空,則根節點已經為葉子節點。

3、遞歸求解樹。将左子樹和右子樹分别看成一棵二叉樹,重複1、2、3步,直到所有的節點完成定位。

舉例說明:根據已知求解二叉樹

中序序列 HLDBEKAFCG

後序序列 LHDKEBFGCA

1、在後序序列LHDKEBFGCA中最後出現的元素為A,HLDBEK|A|FCG

2、在後序序列LHDKEB中最後出現的元素為B,HLD|B|EK|A|FCG

3、在後序序列LHD中最後出現的元素為D,HL|D|B|EK|A|FCG

4、在後序序列LH中最後出現的元素為H,H|L|D|B|EK|A|FCG

5、在後序序列KE中最後出現的元素為E,H|L|D|B|E|K|A|FCG

5、在後序序列FGC中最後出現的元素為C,H|L|D|B|E|K|A|F|C|G

6、所有元素都已經定位,二叉樹求解完成。

A
              /     \
             B       C
            / \     /  \
           D  E     F   G
          /    \
         H      K                    
          \                         
           L                           
代碼如下:      
/*
     功能: 1.利用樹的前序和中序序列建立樹
           2.利用樹的後序和中序序列建立樹
 */
 #include <iostream>
 #include <cstring>
 using namespace std;

 char pre[50] = "ABDHLEKCFG";        //前序序列
 char mid[50] = "HLDBEKAFCG";        //中序序列
 char post[50] = "LHDKEBFGCA";        //後序序列

 typedef struct _Node
 {
     char v;
     struct _Node *left;
     struct _Node *right;
     _Node(){left=NULL;right=NULL;}
 }Node, *PNode;

 void PostTravelTree(PNode pn);        //樹的後序遞歸周遊
 void PreTravelTree(PNode pn);        //樹的前序遞歸周遊
 void PreMidCreateTree(PNode &pn, int i, int j, int len);        //利用前序中序序列建立樹
 void PostMidCreateTree(PNode &pn, int i, int j, int len);        //利用後序中序序列建立樹
 int Position(char c);                //确定c在中序序列mid中的下标,假設樹的各個節點的值各不相同


 int main()
 {
     PNode root1 = NULL, root2= NULL;

     PreMidCreateTree(root1, 0, 0, strlen(mid));
     PostTravelTree(root1); cout<<endl;
     PostMidCreateTree(root2, strlen(post)-1, 0, strlen(mid));
     PreTravelTree(root2); cout<<endl;

     return 0;
 }


 int Position(char c)
 {
     return strchr(mid,c)-mid;
 }


 /*  利用前序中序序列建立樹,參考了http://hi.baidu.com/sulipol/blog/item/f01a20011dcce31a738b6524.html
  *        i: 子樹的前序序列字元串的首字元在pre[]中的下标
  *        j: 子樹的中序序列字元串的首字元在mid[]中的下标
  *      len: 子樹的字元串序列的長度
  */
 void PreMidCreateTree(PNode &pn, int i, int j, int len)
 {
     if(len <= 0)
         return;

     pn = new Node;
     pn->v = pre[i];
     int m = Position(pre[i]);
     PreMidCreateTree(pn->left, i+1, j, m-j);            //m-j為左子樹字元串長度
     PreMidCreateTree(pn->right, i+(m-j)+1, m+1, len-1-(m-j));    //len-1-(m-j)為右子樹字元串長度
 }


 /*  利用後序中序序列建立樹
  *        i: 子樹的後序序列字元串的尾字元在post[]中的下标
  *        j: 子樹的中序序列字元串的首字元在mid[]中的下标
  *      len: 子樹的字元串序列的長度
  */
 void PostMidCreateTree(PNode &pn, int i, int j, int len)
 {
     if(len <= 0)
         return;

     pn = new Node;
     pn->v = post[i];
     int m = Position(post[i]);
     PostMidCreateTree(pn->left, i-1-(len-1-(m-j)), j, m-j);//注意參數:m-j左子樹的長度,len-1-(m-j)右子樹的長度
     PostMidCreateTree(pn->right, i-1, m+1, len-1-(m-j));
 }


 void PostTravelTree(PNode pn)        //後序遞歸周遊
 {
     if(pn)
     {
         PostTravelTree(pn->left);
         PostTravelTree(pn->right);
         cout<<pn->v<<" ";
     }
 }


 void PreTravelTree(PNode pn)        //前序遞歸周遊
 {
     if(pn)
     {
         cout<<pn->v<<" ";
         PreTravelTree(pn->left);
         PreTravelTree(pn->right);
     }
 }
           

繼續閱讀