在學算法結構時,發現了這個問題,雖然在上數據結構時老師講過,但是隻講過具體例子,沒有讓我們訓練代碼,借這次機會,上網查找了相關資料,而且這學期又剛好在學C++,感覺真的可以好好學一下。。。在網上找的資料,貼在這裏和大家共享
這種題一般有二種形式,共同點是都已知中序序列。如果沒有中序序列,是無法唯一確定一棵樹的,證明略。
一、已知二叉樹的前序序列和中序序列,求解樹。
1、確定樹的根節點。樹根是當前樹中所有元素在前序遍歷中最先出現的元素。
2、求解樹的子樹。找出根節點在中序遍歷中的位置,根左邊的所有元素就是左子樹,根右邊的所有元素就是右子樹。若根節點左邊或右邊爲空,則該方向子樹爲空;若根節點左邊和右邊都爲空,則根節點已經爲葉子節點。
3、遞歸求解樹。將左子樹和右子樹分別看成一棵二叉樹,重複1、2、3步,直到所有的節點完成定位。
二、已知二叉樹的後序序列和中序序列,求解樹。
1、確定樹的根。樹根是當前樹中所有元素在後序遍歷中最後出現的元素。
2、求解樹的子樹。找出根節點在中序遍歷中的位置,根左邊的所有元素就是左子樹,根右邊的所有元素就是右子樹。若根節點左邊或右邊爲空,則該方向子樹爲空;若根節點左邊和右邊都爲空,則根節點已經爲葉子節點。
3、遞歸求解樹。將左子樹和右子樹分別看成一棵二叉樹,重複1、2、3步,直到所有的節點完成定位。
舉例說明:根據已知求解二叉樹
中序序列 HLDBEKAFCG
後序序列 LHDKEBFGCA
1、在後序序列LHDKEBFGCA中最後出現的元素爲A,HLDBEK|A|FCG
2、在後序序列LHDKEB中最後出現的元素爲B,HLD|B|EK|A|FCG
3、在後序序列LHD中最後出現的元素爲D,HL|D|B|EK|A|FCG
4、在後序序列LH中最後出現的元素爲H,H|L|D|B|EK|A|FCG
5、在後序序列KE中最後出現的元素爲E,H|L|D|B|E|K|A|FCG
5、在後序序列FGC中最後出現的元素爲C,H|L|D|B|E|K|A|F|C|G
6、所有元素都已經定位,二叉樹求解完成。
A / / B C / / / / D E F G / / H K / L
代碼如下:
2 功能: 1.利用樹的前序和中序序列創建樹
3 2.利用樹的後序和中序序列創建樹
4 */
5 #include <iostream>
6 #include <cstring>
7 using namespace std;
8
9 char pre[50] = "ABDHLEKCFG"; //前序序列
10 char mid[50] = "HLDBEKAFCG"; //中序序列
11 char post[50] = "LHDKEBFGCA"; //後序序列
12
13 typedef struct _Node
14 {
15 char v;
16 struct _Node *left;
17 struct _Node *right;
18 }Node, *PNode;
19
20 void PostTravelTree(PNode pn); //樹的後序遞歸遍歷
21 void PreTravelTree(PNode pn); //樹的前序遞歸遍歷
22 void PreMidCreateTree(PNode &pn, int i, int j, int len); //利用前序中序序列創建樹
23 void PostMidCreateTree(PNode &pn, int i, int j, int len); //利用後序中序序列創建樹
24 int Position(char c); //確定c在中序序列mid中的下標,假設樹的各個節點的值各不相同
25
26
27 int main()
28 {
29 PNode root1 = NULL, root2= NULL;
30
31 PreMidCreateTree(root1, 0, 0, strlen(mid));
34 PostTravelTree(root1); cout<<endl;
36 PostMidCreateTree(root2, strlen(post)-1, 0, strlen(mid));
37 PreTravelTree(root2); cout<<endl;
38
39 return 0;
40 }
41
42
43 int Position(char c)
44 {
45 return strchr(mid,c)-mid;
46 }
47
48
49 /* 利用前序中序序列創建樹,參考了http://hi.baidu.com/sulipol/blog/item/f01a20011dcce31a738b6524.html
50 *的實現,代碼十分簡潔,竟然只有短短的"令人髮指"的8行,遞歸實在太彪悍了!!!!!!!!!!!!!!!!!!!!!
51 * i: 子樹的前序序列字符串的首字符在pre[]中的下標
52 * j: 子樹的中序序列字符串的首字符在mid[]中的下標
53 * len: 子樹的字符串序列的長度
54 */
55 void PreMidCreateTree(PNode &pn, int i, int j, int len)
56 {
57 if(len <= 0)
58 {
59
60 pn = new Node;
61 pn->v = pre[i];
62 int m = Position(pre[i]);
63 PreMidCreateTree(pn->left, i+1, j, m-j); //m-j爲左子樹字符串長度
64 PreMidCreateTree(pn->right, i+(m-j)+1, m+1, len-1-(m-j)); //len-1-(m-j)爲右子樹字符串長度
65 }
66
67
68 /* 利用後序中序序列創建樹
69 * i: 子樹的後序序列字符串的尾字符在post[]中的下標
70 * j: 子樹的中序序列字符串的首字符在mid[]中的下標
71 * len: 子樹的字符串序列的長度
72 */
73 void PostMidCreateTree(PNode &pn, int i, int j, int len)
74 {
75 if(len <= 0)
76 return;
77
78 pn = new Node;
79 pn->v = post[i];
80 int m = Position(post[i]);
81 PostMidCreateTree(pn->left, i-1-(len-1-(m-j)), j, m-j);//注意參數:m-j左子樹的長度,len-1-(m-j)右子樹的長度
82 PostMidCreateTree(pn->right, i-1, m+1, len-1-(m-j));
83 }
84
85
86 void PostTravelTree(PNode pn) //後序遞歸遍歷
87 {
88 if(pn)
89 {
90 PostTravelTree(pn->left);
91 PostTravelTree(pn->right);
92 cout<<pn->v<<" ";
93 }
94 }
95
96
97 void PreTravelTree(PNode pn) //前序遞歸遍歷
98 {
99 if(pn)
100 {
101 cout<<pn->v<<" ";
102 PreTravelTree(pn->left);
103 PreTravelTree(pn->right);
104 }
105 }
參考網站 http://www.cnblogs.com/bmrs/archive/2010/08/19/slovetree.html