在學二叉樹的重建時,在《算法筆記》上學到了如何通過先序(或后序)遍歷序列和中序遍歷序列重建二叉樹,它也提出了一個問題:如何通過層序和中序遍歷序列重建二叉樹?我一開始按照先序和中序重建的思路思考,發現做不到。我無法確定一個點后面的點屬於它的左子樹還是右子樹或者兄弟節點。於是我在網上查找,發現這方面的話題不多,其中還有一些不是用C++實現的。不過幸好還是找到了。於是在學習之后在這把它記錄下來。
1 #include <cstdio> 2 3 const int INF = 0x3fffffff; 4 const int maxn = 10010; 5 6 struct Node 7 { 8 int x; 9 Node *left, *right; 10 }; 11 12 Node* root; 13 int levelorder[maxn], inorder[maxn]; 14 int n; 15 bool hashtable[maxn]; //標記levelorder中某個點是否被加入了樹中 16 //如果沒有hashtable, 當樹中存在兩個值相等的點時 , 17 Node* init() //可能導致在層序遍歷中相同值的兩個點前面的點被遍歷兩次,后面的點 18 { //沒有被遍歷,從而建樹錯誤 19 Node* node = new Node; 20 node->x = 0; 21 node->left = NULL; 22 node->right = NULL; 23 return node; 24 } 25 26 Node* buildtree(int il, int ir, int ll, int lr) //當我給你一個二叉樹的中序遍歷時 27 { //這個中序遍歷遍歷一定有一個根節點 28 if(il == ir) //體現在層序遍歷上時它一定先出現 29 { //所以順序遍歷層序遍歷,一定可以先發現二叉樹的根節點 30 Node* node = new Node; 31 node->x = inorder[il]; 32 hashtable[il] = true; 33 return node; 34 } 35 Node* node = new Node; 36 int i, j; 37 for(j = ll; j <= lr; j++) 38 { 39 bool flag = false; 40 for(i = il; i <= ir; i++) 41 { 42 if(inorder[i] == levelorder[j]&&hashtable[i] == false) 43 { 44 flag = true; 45 break; 46 } 47 } 48 if(flag) break; 49 } 50 node->left = buildtree(il, i-1, j+1, lr); 51 node->right = buildtree(i+1, ir, j+1, lr); 52 node->x = inorder[i]; 53 hashtable[i] = true; 54 return node; 55 } 56 57 int main() 58 { 59 scanf("%d", &n); 60 for(int i = 0; i < n; i++) scanf("%d", &inorder[i]); 61 for(int i = 0; i < n; i++) scanf("%d", &levelorder[i]); 62 root = buildtree(0, n-1, 0, n-1); 63 printf("%d\n", root->left->right->x); 64 return 0; 65 }
這個重建的方法利用了層序遍歷序列中父子節點有先后順序的特點。
