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


轉自:http://www.cnblogs.com/bmrs/archive/2010/08/19/SloveTree.html

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

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

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          

 

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  1 /*
    功能: 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, *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
 *的實現,代碼十分簡潔,竟然只有短短的"令人發指"的8行,遞歸實在太彪悍了!!!!!!!!!!!!!!!!!!!!!
 *        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);
    }
}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM