1 // 面试题7:重建二叉树
2 // 题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输
3 // 入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,
4 // 2, 4, 7, 3, 5, 6, 8}和中序遍历序列{4, 7, 2, 1, 5, 3, 8, 6},则重建出
5 // 图2.6所示的二叉树并输出它的头结点。
6
7 #include <iostream>
8 #include <exception>
9 #include <cstdio>
10 #include<stdexcept>
11 using namespace std;
12
13 struct BinaryTreeNode
14 {
15 int m_nValue;
16 BinaryTreeNode* m_pLeft;
17 BinaryTreeNode* m_pRight;
18 };
19
20 BinaryTreeNode* CreateBinaryTreeNode(int value)
21 {
22 BinaryTreeNode* pNode = new BinaryTreeNode();
23 pNode->m_nValue = value;
24 pNode->m_pLeft = nullptr;
25 pNode->m_pRight = nullptr;
26
27 return pNode;
28 }
29
30 void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight)
31 {
32 if(pParent != nullptr)
33 {
34 pParent->m_pLeft = pLeft;
35 pParent->m_pRight = pRight;
36 }
37 }
38
39 void PrintTreeNode(const BinaryTreeNode* pNode)
40 {
41 if(pNode != nullptr)
42 {
43 printf("value of this node is: %d\n", pNode->m_nValue);
44
45 if(pNode->m_pLeft != nullptr)
46 printf("value of its left child is: %d.\n", pNode->m_pLeft->m_nValue);
47 else
48 printf("left child is nullptr.\n");
49
50 if(pNode->m_pRight != nullptr)
51 printf("value of its right child is: %d.\n", pNode->m_pRight->m_nValue);
52 else
53 printf("right child is nullptr.\n");
54 }
55 else
56 {
57 printf("this node is nullptr.\n");
58 }
59
60 printf("\n");
61 }
62
63 void PrintTree(const BinaryTreeNode* pRoot)
64 {
65 PrintTreeNode(pRoot);
66
67 if(pRoot != nullptr)
68 {
69 if(pRoot->m_pLeft != nullptr)
70 PrintTree(pRoot->m_pLeft);
71
72 if(pRoot->m_pRight != nullptr)
73 PrintTree(pRoot->m_pRight);
74 }
75 }
76
77 void DestroyTree(BinaryTreeNode* pRoot)
78 {
79 if(pRoot != nullptr)
80 {
81 BinaryTreeNode* pLeft = pRoot->m_pLeft;
82 BinaryTreeNode* pRight = pRoot->m_pRight;
83
84 delete pRoot;
85 pRoot = nullptr;
86
87 DestroyTree(pLeft);
88 DestroyTree(pRight);
89 }
90 }
91
92 BinaryTreeNode* ConstructCore(int* startPreorder, int* endPreorder, int* startInorder, int* endInorder);
93
94 BinaryTreeNode* Construct(int* preorder, int* inorder, int length)
95 {
96 if(preorder == nullptr || inorder == nullptr || length <= 0)
97 return nullptr;
98
99 return ConstructCore(preorder, preorder + length - 1,
100 inorder, inorder + length - 1);
101 }
102
103 BinaryTreeNode* ConstructCore
104 (
105 int* startPreorder, int* endPreorder,
106 int* startInorder, int* endInorder
107 )
108 {
109 // 前序遍历序列的第一个数字是根结点的值
110 int rootValue = startPreorder[0];
111 BinaryTreeNode* root = new BinaryTreeNode();
112 root->m_nValue = rootValue;
113 root->m_pLeft = root->m_pRight = nullptr;
114
115 if(startPreorder == endPreorder)
116 {
117 if(startInorder == endInorder && *startPreorder == *startInorder)
118 return root;
119 else
120 {
121 std::logic_error ex("Invalid input.");
122 throw std::exception(ex);
123 }
124 // throw exception("Invalid input.");
125 }
126
127 // 在中序遍历中找到根结点的值
128 int* rootInorder = startInorder;
129 while(rootInorder <= endInorder && *rootInorder != rootValue)
130 ++ rootInorder;
131
132 if(rootInorder == endInorder && *rootInorder != rootValue)
133 {
134 std::logic_error ex("Invalid input.");
135 throw std::exception(ex);
136 }
137 // throw std::exception("Invalid input.");
138
139 int leftLength = rootInorder - startInorder;
140 int* leftPreorderEnd = startPreorder + leftLength;
141 if(leftLength > 0)
142 {
143 // 构建左子树
144 root->m_pLeft = ConstructCore(startPreorder + 1, leftPreorderEnd,
145 startInorder, rootInorder - 1);
146 }
147 if(leftLength < endPreorder - startPreorder)
148 {
149 // 构建右子树
150 root->m_pRight = ConstructCore(leftPreorderEnd + 1, endPreorder,
151 rootInorder + 1, endInorder);
152 }
153
154 return root;
155 }
156
157 // ====================测试代码====================
158 void Test(char* testName, int* preorder, int* inorder, int length)
159 {
160 if(testName != nullptr)
161 printf("%s begins:\n", testName);
162
163 printf("The preorder sequence is: ");
164 for(int i = 0; i < length; ++ i)
165 printf("%d ", preorder[i]);
166 printf("\n");
167
168 printf("The inorder sequence is: ");
169 for(int i = 0; i < length; ++ i)
170 printf("%d ", inorder[i]);
171 printf("\n");
172
173 try
174 {
175 BinaryTreeNode* root = Construct(preorder, inorder, length);
176 PrintTree(root);
177
178 DestroyTree(root);
179 }
180 catch(std::exception& exception)
181 {
182 printf("Invalid Input.\n");
183 }
184 }
185
186 // 普通二叉树
187 // 1
188 // / \
189 // 2 3
190 // / / \
191 // 4 5 6
192 // \ /
193 // 7 8
194 void Test1()
195 {
196 const int length = 8;
197 int preorder[length] = {1, 2, 4, 7, 3, 5, 6, 8};
198 int inorder[length] = {4, 7, 2, 1, 5, 3, 8, 6};
199
200 Test("Test1", preorder, inorder, length);
201 }
202
203 // 所有结点都没有右子结点
204 // 1
205 // /
206 // 2
207 // /
208 // 3
209 // /
210 // 4
211 // /
212 // 5
213 void Test2()
214 {
215 const int length = 5;
216 int preorder[length] = {1, 2, 3, 4, 5};
217 int inorder[length] = {5, 4, 3, 2, 1};
218
219 Test("Test2", preorder, inorder, length);
220 }
221
222 // 所有结点都没有左子结点
223 // 1
224 // \
225 // 2
226 // \
227 // 3
228 // \
229 // 4
230 // \
231 // 5
232 void Test3()
233 {
234 const int length = 5;
235 int preorder[length] = {1, 2, 3, 4, 5};
236 int inorder[length] = {1, 2, 3, 4, 5};
237
238 Test("Test3", preorder, inorder, length);
239 }
240
241 // 树中只有一个结点
242 void Test4()
243 {
244 const int length = 1;
245 int preorder[length] = {1};
246 int inorder[length] = {1};
247
248 Test("Test4", preorder, inorder, length);
249 }
250
251 // 完全二叉树
252 // 1
253 // / \
254 // 2 3
255 // / \ / \
256 // 4 5 6 7
257 void Test5()
258 {
259 const int length = 7;
260 int preorder[length] = {1, 2, 4, 5, 3, 6, 7};
261 int inorder[length] = {4, 2, 5, 1, 6, 3, 7};
262
263 Test("Test5", preorder, inorder, length);
264 }
265
266 // 输入空指针
267 void Test6()
268 {
269 Test("Test6", nullptr, nullptr, 0);
270 }
271
272 // 输入的两个序列不匹配
273 void Test7()
274 {
275 const int length = 7;
276 int preorder[length] = {1, 2, 4, 5, 3, 6, 7};
277 int inorder[length] = {4, 2, 8, 1, 6, 3, 7};
278
279 Test("Test7: for unmatched input", preorder, inorder, length);
280 }
281
282 int main(int argc, char* argv[])
283 {
284 Test1();
285 Test2();
286 Test3();
287 Test4();
288 Test5();
289 Test6();
290 Test7();
291
292 return 0;
293 }