剑指offer——面试题7:重建二叉树

  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 }
View Code

 

posted @ 2019-02-16 16:57  Run_For_Love  阅读(222)  评论(0编辑  收藏  举报