二叉樹的遍歷方式有4種:先序遍歷,中序遍歷,后序遍歷以及層次遍歷
根據中序遍歷和另外任意一種遍歷方式都可以唯一的重建二叉樹!
如果沒有中序遍歷,其余任意兩種組合均無法實現二叉樹的重建,為什么?
其實原因很簡單,先中后說的均為根結點的順序,那么左子樹一定先於右子樹遍歷到,中序遍歷可以根據根結點,將左右子樹分開!
那么如何根據中序遍歷和后序遍歷,重建出二叉樹?
思路:假設遞歸過程中,某一步的后序序列區間為[postL,postR],中序序列區間為[inL,inR];
1. 根據后序遍歷的特點可知,postR位置為根結點;
2. 從中序序列中,尋找出root的位置k,k左邊的均為左子樹,右邊的均為右子樹;
3. 將左子樹區間[postL,k-1]作為新的后序和中序序列,進行遞歸。
代碼如下:
/* * 給定一個二叉樹的后序遍歷和中序遍歷,重建這個二叉樹 */ /* * 思路:根據后序遍歷找到根結點,根據中序遍歷,根結點左邊為左子樹,根結點右邊為右子樹 * 邊界條件:后序區間為空 */ #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; const int maxn=50; struct node{ int data; node* lchild; node* rchild; }; int pre[maxn],in[maxn],post[maxn]; int n; node* create(int postL,int postR,int inL,int inR) //后序和中序的區間 { if(postL>postR) return NULL; node* root=new node; root->data=post[postR]; //后序序列中,最后一個節點為根節點 int k; for(k=inL;k<=inR;k++) { if(in[k]==root->data) break; } int numLeft=k-inL; //左子區間為左子樹0 root->lchild=create(postL,postL+numLeft-1,inL,k-1); root->rchild=create(postL+numLeft,postR-1,k+1,inR); return root; } int num=0; void BFS(node *root){ //層次遍歷 queue<node*> q; q.push(root); while(!q.empty()){ node* now=q.front(); q.pop(); printf("%d",now->data); num++; if(num<n) printf(" "); if(now->lchild!=NULL) q.push(now->lchild); if(now->rchild!=NULL) q.push(now->rchild); } } int main() { scanf("%d",&n); int i; for(i=0;i<n;i++){ scanf("%d",&post[i]); } for(i=0;i<n;i++){ scanf("%d",&in[i]); } node* root=create(0,n-1,0,n-1); BFS(root);
prinf("\n"); return 0; }
僅供學習參考!
測試用例:【PAT A1020】