二叉樹前序、中序、後序遍曆相互求法
今天來總結下二叉樹前序、中序、後序遍曆相互求法,即如果知道兩個的遍曆,如何求第三種遍曆方法,比較笨的方法是畫出來二叉樹,然後根據各種遍曆不同的特性來求,也可以編程求出,下麵我們分別說明。
首先,我們看看前序、中序、後序遍曆的特性:
前序遍曆:
1.訪問根節點
2.前序遍曆左子樹
3.前序遍曆右子樹
中序遍曆:
1.中序遍曆左子樹
2.訪問根節點
3.中序遍曆右子樹
後序遍曆:
1.後序遍曆左子樹
2.後序遍曆右子樹
3.訪問根節點
一、已知前序、中序遍曆,求後序遍曆
例:
前序遍曆: GDAFEMHZ
中序遍曆: ADEFGHMZ
畫樹求法:
第一步,根據前序遍曆的特點,我們知道根結點為G
第二步,觀察中序遍曆ADEFGHMZ。其中root節點G左側的ADEF必然是root的左子樹,G右側的HMZ必然是root的右子樹。
第三步,觀察左子樹ADEF,左子樹的中的根節點必然是大樹的root的leftchild。在前序遍曆中,大樹的root的leftchild位於root之後,所以左子樹的根節點為D。
第四步,同樣的道理,root的右子樹節點HMZ中的根節點也可以通過前序遍曆求得。在前序遍曆中,一定是先把root和root的所有左子樹節點遍曆完之後才會遍曆右子樹,並且遍曆的左子樹的第一個節點就是左子樹的根節點。同理,遍曆的右子樹的第一個節點就是右子樹的根節點。
第五步,觀察發現,上麵的過程是遞歸的。先找到當前樹的根節點,然後劃分為左子樹,右子樹,然後進入左子樹重複上麵的過程,然後進入右子樹重複上麵的過程。最後就可以還原一棵樹了。該步遞歸的過程可以簡潔表達如下:
1 確定根,確定左子樹,確定右子樹。
2 在左子樹中遞歸。
3 在右子樹中遞歸。
4 打印當前根。
那麼,我們可以畫出這個二叉樹的形狀:

那麼,根據後序的遍曆規則,我們可以知道,後序遍曆順序為:AEFDHZMG
編程求法:(依據上麵的思路,寫遞歸程序)
1 #include <iostream>
2 #include <fstream>
3 #include <string>
4
5 struct TreeNode
6 {
7 struct TreeNode* left;
8 struct TreeNode* right;
9 char elem;
10 };
11
12 void BinaryTreeFromOrderings(char* inorder, char* preorder, int length)
13 {
14 if(length == 0)
15 {
16 //cout<<"invalid length";
17 return;
18 }
19 TreeNode* node = new TreeNode;//Noice that [new] should be written out.
20 node->elem = *preorder;
21 int rootIndex = 0;
22 for(;rootIndex < length; rootIndex++)
23 {
24 if(inorder[rootIndex] == *preorder)
25 break;
26 }
27 //Left
28 BinaryTreeFromOrderings(inorder, preorder +1, rootIndex);
29 //Right
30 BinaryTreeFromOrderings(inorder + rootIndex + 1, preorder + rootIndex + 1, length - (rootIndex + 1));
31 cout<<node->elem<<endl;
32 return;
33 }
34
35
36 int main(int argc, char* argv[])
37 {
38 printf("Hello World!\n");
39 char* pr="GDAFEMHZ";
40 char* in="ADEFGHMZ";
41
42 BinaryTreeFromOrderings(in, pr, 8);
43
44 printf("\n");
45 return 0;
46 }
輸出的結果為:AEFDHZMG
二、已知中序和後序遍曆,求前序遍曆
依然是上麵的題,這次我們隻給出中序和後序遍曆:
中序遍曆: ADEFGHMZ
後序遍曆: AEFDHZMG
畫樹求法:
第一步,根據後序遍曆的特點,我們知道後序遍曆最後一個結點即為根結點,即根結點為G。
第二步,觀察中序遍曆ADEFGHMZ。其中root節點G左側的ADEF必然是root的左子樹,G右側的HMZ必然是root的右子樹。
第三步,觀察左子樹ADEF,左子樹的中的根節點必然是大樹的root的leftchild。在前序遍曆中,大樹的root的leftchild位於root之後,所以左子樹的根節點為D。
第四步,同樣的道理,root的右子樹節點HMZ中的根節點也可以通過前序遍曆求得。在前後序遍曆中,一定是先把root和root的所有左子樹節點遍曆完之後才會遍曆右子樹,並且遍曆的左子樹的第一個節點就是左子樹的根節點。同理,遍曆的右子樹的第一個節點就是右子樹的根節點。
第五步,觀察發現,上麵的過程是遞歸的。先找到當前樹的根節點,然後劃分為左子樹,右子樹,然後進入左子樹重複上麵的過程,然後進入右子樹重複上麵的過程。最後就可以還原一棵樹了。該步遞歸的過程可以簡潔表達如下:
1 確定根,確定左子樹,確定右子樹。
2 在左子樹中遞歸。
3 在右子樹中遞歸。
4 打印當前根。
這樣,我們就可以畫出二叉樹的形狀,如上圖所示,這裏就不再贅述。
那麼,前序遍曆: GDAFEMHZ
編程求法:(並且驗證我們的結果是否正確)
#include <iostream>
#include <fstream>
#include <string>
struct TreeNode
{
struct TreeNode* left;
struct TreeNode* right;
char elem;
};
TreeNode* BinaryTreeFromOrderings(char* inorder, char* aftorder, int length)
{
if(length == 0)
{
return NULL;
}
TreeNode* node = new TreeNode;//Noice that [new] should be written out.
node->elem = *(aftorder+length-1);
std::cout<<node->elem<<std::endl;
int rootIndex = 0;
for(;rootIndex < length; rootIndex++)//a variation of the loop
{
if(inorder[rootIndex] == *(aftorder+length-1))
break;
}
node->left = BinaryTreeFromOrderings(inorder, aftorder , rootIndex);
node->right = BinaryTreeFromOrderings(inorder + rootIndex + 1, aftorder + rootIndex , length - (rootIndex + 1));
return node;
}
int main(int argc, char** argv)
{
char* af="AEFDHZMG";
char* in="ADEFGHMZ";
BinaryTreeFromOrderings(in, af, 8);
printf("\n");
return 0;
}
輸出結果:GDAFEMHZ
最後更新:2017-04-03 14:54:20