假設已知先序序列為pre1,pre2,pre3……pren,中序序列為in1,in2,in3,……,inn,如圖所示,那麼由先序序列的性質可知,先序序列的第乙個元素pre1是當前二叉樹的根節點,再由中序序列的性質可知,當前二叉樹的根節點將中序序列劃分為左子樹和右子樹。因此,要做的就是在中序序列中找到某個結點ink,使的ink==pre1,這樣就在中序序列中找到了根節點。易知左子樹的結點個數是numleft=k-1.於是,左子樹的先序序列區間就是[2,k],左子樹的中序序列區間就是[1,k-1];右子樹的先序序列區間就是[2,k],右子樹的中序序列區間是[k+1,n],接著只需要在左子樹和右子樹上進行遞迴重建二叉樹即可。
事實上,如果遞迴過程中當前序列的區間為[prel,prer],中序序列的區間為[inl.inr],那麼左子樹的結點個數為numleft=k-inl.這樣左子樹的先序序列區間為[prel+1,prel+numleft],左子樹的中序序列區間為[inl,k-1];右子樹的先序序列區間為[prel+numleft+1,prer],右子樹的中序序列區間為[k+1,inr];
那麼,如果一直這樣遞迴下去,什麼時候結束呢?問題的答案是顯然的,因為只要先序序列的長度小於等於0時,當前二叉樹就不存在了,以此作為遞迴的邊界。
**如下:
//當前先序序列的區間為[prel,prer],中序序列的區間為[inl,inr]
node *create(int prel,int prer,int inl,int inr)
node *root=new node;//新建乙個結點,用來存放當前二叉樹的根節點
root->data=pre[prel];//新結點的資料域為根節點的值
int k;
for(k=inl,k<=inr;k++)
int numleft=k-inl;//左子樹的結點個數
//左子樹的先序區間為[prel+1,prel+numleft],中序區間為[inl,k-1]
//返回左子樹的根節點的位址,賦值給root的左指標
root->lchild=create(prel+1,prel+numleft,inl,k-1);
//右子樹的先序序列區間為[prel+numleft+1,prer],中序區間為[k+1,inr]
//返回右子樹的根結點的位址,賦值給root的右指標
root->rchild=create(prel+numleft+1,prer,k+1,inr);
return root;//返回根節點的位址
}
上面的**就重建了一顆二叉樹
重要結論:
中序序列可以與先序序列、後序序列和層次序列中的任意乙個來重建乙個唯一的二叉樹,而後三者兩兩搭配或是三者一起都無法重建唯一的二叉樹。原因是先序、後序、層次遍歷均是提供根結點的,作用是相同的,都必須由中序序列來區分左子樹和右子樹。
先序中序重建二叉樹
includeusing namespace std vectorpre,in int p typedef struct node vectorpost int rec int l,int r 通過前序和後序得到樹 int main for int i 0 i tem in.push back te...
已知中序遍歷和先序遍歷重建二叉樹
main.cpp constructbinarytree created by bazinga on 2017 3 12.根據前序遍歷和中序遍歷求二叉樹的結構 已知前序遍歷的第乙個值為根節點 而根節點在中序遍歷中的位置就能確定他的左右子樹。然後對區分開的左右子樹進行遞迴。include includ...
根據二叉樹的先序遍歷和中序遍歷重建二叉樹
輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列和中序遍歷序列,則重建二叉樹並返回。public class solution int in treenode root reconstructbinarytree p...