二叉樹的前中后序遍歷,他們的遞歸非遞歸。還有廣度遍歷,參見二叉樹的前中后序遍歷迭代&廣度遍歷和二叉樹的前中后序遍歷簡單的遞歸
現在記錄已知二叉樹的前序中序后序遍歷的兩個,求另外一個。一般,這兩個中一定有中序遍歷。
1、已知前序和中序,求后序遍歷:
前序:ABDECFG 中序:DBEAFCG
思路簡單:前序的第一個節點就是根節點,
中序中找到根節點的位置,根節點之前是其左子樹,之后是右子樹
按此順序,依次在左子樹部分遍歷,右子樹部分遍歷
C++ 代碼:
TreeNode *BinaryTreeFormorderings(char *Preorder, char *Inorder, int len) { if(len == 0) return NULL; TreeNode *node=new TreeNode; node->val=*Preorder; int rootIndex=0; while(rootIndex<len) { if(Inorder[rootIndex] == *Preorder) break; ++rootIndex; } node->left = BinaryTreeFormorderings(Preorder+1, Inorder, rootIndex); node->right = BinaryTreeFormorderings(Preorder+rootIndex+1,Inorder+rootIndex+1,len-(rootIndex+1)); cout<<node->val; return node; }
注:上述代碼,其實是在遍歷的過程中建立了一個二叉樹並返回,這是最全的。如果只是要個后續遍歷的序列,可以在輸出哪里以一個vector來存放序列就可以了,沒必要建立二叉樹的。如果只是要輸出后續遍歷,則在最后哪里輸出就可以了,也沒必要保存這個vector了。
2、已知后和中序,求前序遍歷:類似上述求后序的情況
后序:DEBFGCA 中序:DBEAFCG
思路簡單:后序的最后一個節點就是根節點,
中序中找到根節點的位置,根節點之前是其左子樹,之后是右子樹
按此順序,依次在左子樹部分遍歷,右子樹部分遍歷
C++代碼:
TreeNode *BinaryTreePostorderings(char *Postorder, char *Inorder, int len) { if (len == 0) return NULL; TreeNode *node = new TreeNode; node->val = *(Postorder + len - 1); cout << node->val; int rootIndex = 0; while (rootIndex<len) { if (Inorder[rootIndex] == *(Postorder + len - 1)) break; ++rootIndex; } node->left = BinaryTreePostorderings(Postorder, Inorder, rootIndex); node->right = BinaryTreePostorderings(Postorder + rootIndex, Inorder + rootIndex + 1, len - (rootIndex + 1)); return node; }
注:上述代碼,與前文情況一致,根據具體情況需要來完成前序的遍歷。
又寫了一次遍歷方式,用vector存放數據,起點終點,函數參數傳入:
void BinaryTree::PreIn_to_post(std::vector<int> &pre, int first, int end, std::vector<int> &in, int first2, int end2, std::vector<int> &post) { if (pre.size() == 0 || in.size() == 0 || first<0 || end>pre.size()-1 || first2<0 || end2>in.size()-1 ||first>end || first2>end2 || end-first != end2-first2) return; if (first == end) { post.push_back(pre[first]); return; } int index2 = first2; while (index2 <= end2 && in[index2] != pre[first]) ++index2; PreIn_to_post(pre, first + 1, first+index2-first2, in, first2, index2-1, post); PreIn_to_post(pre, first+ 1+index2 -first2, end, in, index2 + 1, end2, post); post.push_back(pre[first]); } void BinaryTree::PostIn_to_pre(std::vector<int> &post, int first, int end, std::vector<int> &in, int first2, int end2, std::vector<int> &pre) { if (post.size() == 0 || in.size() == 0 || first<0 || end>post.size() - 1 || first2<0 || end2>in.size() - 1 || first > end || first2 > end2 || end - first != end2 - first2) return; if (first == end) { pre.push_back(post[end]); return; } int index2 = first2; while (index2 <= end2&&in[index2] != post[end]) ++index2; pre.push_back(post[end]); PostIn_to_pre(post, first, first + (index2 - first2)-1, in, first2, index2 - 1, pre); PostIn_to_pre(post, first + index2 - first2, end - 1, in, index2 + 1, end2,pre); }
3、已知前序后序遍歷,求中序遍歷:
這種情況並不能完全的求出所有情況的二叉樹中序遍歷。因為由前序和后序並不能完全確定一顆樹。但是,如果已知是滿二叉樹或者完全二叉樹的話,我想是可以的。
前序:中左右 后序:左右中
思路是這樣的:
前序的第一個節點和后序的最后一個節點一定是根節點,
如果前序的第二個節點與后序的倒數第二個節點不相等,那么前序的第二節點是根的左子樹,后序的倒數第二節點是根的右子樹
(但是 如果前序的第二個節點與后序的倒數第二個節點相等,那就不能確定到底是左子樹還是右子樹了,因為缺省一個子樹中左與左中,中右與右中都會相等。所以這就需要題目有要求該樹的特征了)
然后再后序中找到左子樹根節點,在后序中從左子樹根節點結合前序左子樹根節點開始遞歸上述得到根節點左子樹的子樹
同樣在前序中找到右子樹根節點,在前序中從右子樹根節點結合后序右子樹根節點開始遞歸上述得到根節點右子樹的子樹
改天想寫代碼的時候再來試試貼上吧