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

Posted cxc1357

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指Offer——面试题7:重建二叉树相关的知识,希望对你有一定的参考价值。

题目:输入某二叉树的前序遍历和中序遍历结果,重建该二叉树。(假设输入的前序和中序遍历结果中都不含重复数字)

  1 #include "BinaryTree.h"
  2 #include <stdexcept>
  3 #include <iostream>
  4 #include <cstdio>
  5 #include <cstdlib>
  6 
  7 BinaryTreeNode* ConstructCore(int* startPreorder, int* endPreorder, int* startInorder, int* endInorder);
  8 
  9 BinaryTreeNode* Construct(int* preorder, int* inorder, int length)
 10 {
 11     if(preorder == nullptr || inorder == nullptr || length <= 0)
 12         return nullptr;
 13 
 14     return ConstructCore(preorder, preorder + length - 1,
 15         inorder, inorder + length - 1);
 16 }
 17 
 18 BinaryTreeNode* ConstructCore
 19 (
 20     int* startPreorder, int* endPreorder, 
 21     int* startInorder, int* endInorder
 22 )
 23 {
 24     // 前序遍历序列的第一个数字是根结点的值
 25     int rootValue = startPreorder[0];
 26     BinaryTreeNode* root = new BinaryTreeNode();
 27     root->m_nValue = rootValue;
 28     root->m_pLeft = root->m_pRight = nullptr;
 29 
 30     if(startPreorder == endPreorder)
 31     {
 32         if(startInorder == endInorder && *startPreorder == *startInorder)
 33             return root;
 34         else
 35             throw -1;
 36     }
 37 
 38     // 在中序遍历中找到根结点的值
 39     int* rootInorder = startInorder;
 40     while(rootInorder <= endInorder && *rootInorder != rootValue)
 41         ++ rootInorder;
 42 
 43     if(rootInorder == endInorder && *rootInorder != rootValue)
 44         throw -1;
 45 
 46     int leftLength = rootInorder - startInorder;
 47     int* leftPreorderEnd = startPreorder + leftLength;
 48     if(leftLength > 0)
 49     {
 50         // 构建左子树
 51         root->m_pLeft = ConstructCore(startPreorder + 1, leftPreorderEnd, 
 52             startInorder, rootInorder - 1);
 53     }
 54     if(leftLength < endPreorder - startPreorder)
 55     {
 56         // 构建右子树
 57         root->m_pRight = ConstructCore(leftPreorderEnd + 1, endPreorder,
 58             rootInorder + 1, endInorder);
 59     }
 60 
 61     return root;
 62 }
 63 
 64 // ====================测试代码====================
 65 void Test(char* testName, int* preorder, int* inorder, int length)
 66 {
 67     if(testName != nullptr)
 68         printf("%s begins:
", testName);
 69 
 70     printf("The preorder sequence is: ");
 71     for(int i = 0; i < length; ++ i)
 72         printf("%d ", preorder[i]);
 73     printf("
");
 74 
 75     printf("The inorder sequence is: ");
 76     for(int i = 0; i < length; ++ i)
 77         printf("%d ", inorder[i]);
 78     printf("
");
 79 
 80     try
 81     {
 82         BinaryTreeNode* root = Construct(preorder, inorder, length);
 83         PrintTree(root);
 84         DestroyTree(root);
 85     }
 86     catch(int d)
 87     {
 88         printf("Invalid Input.
");
 89     }
 90 }
 91 
 92 // 普通二叉树
 93 //              1
 94 //           /      95 //          2       3  
 96 //         /       /  97 //        4       5   6
 98 //                  /
 99 //          7       8
100 void Test1()
101 {
102     const int length = 8;
103     int preorder[length] = {1, 2, 4, 7, 3, 5, 6, 8};
104     int inorder[length] = {4, 7, 2, 1, 5, 3, 8, 6};
105 
106     Test("Test1", preorder, inorder, length);
107 }
108 
109 // 所有结点都没有右子结点
110 //            1
111 //           / 
112 //          2   
113 //         / 
114 //        3 
115 //       /
116 //      4
117 //     /
118 //    5
119 void Test2()
120 {
121     const int length = 5;
122     int preorder[length] = {1, 2, 3, 4, 5};
123     int inorder[length] = {5, 4, 3, 2, 1};
124 
125     Test("Test2", preorder, inorder, length);
126 }
127 
128 // 所有结点都没有左子结点
129 //            1
130 //              
131 //              2   
132 //                
133 //                3 
134 //                 135 //                  4
136 //                   137 //                    5
138 void Test3()
139 {
140     const int length = 5;
141     int preorder[length] = {1, 2, 3, 4, 5};
142     int inorder[length] = {1, 2, 3, 4, 5};
143 
144     Test("Test3", preorder, inorder, length);
145 }
146 
147 // 树中只有一个结点
148 void Test4()
149 {
150     const int length = 1;
151     int preorder[length] = {1};
152     int inorder[length] = {1};
153 
154     Test("Test4", preorder, inorder, length);
155 }
156 
157 // 完全二叉树
158 //              1
159 //           /     160 //          2       3  
161 //         /      / 162 //        4   5   6   7
163 void Test5()
164 {
165     const int length = 7;
166     int preorder[length] = {1, 2, 4, 5, 3, 6, 7};
167     int inorder[length] = {4, 2, 5, 1, 6, 3, 7};
168 
169     Test("Test5", preorder, inorder, length);
170 }
171 
172 // 输入空指针
173 void Test6()
174 {
175     Test("Test6", nullptr, nullptr, 0);
176 }
177 
178 // 输入的两个序列不匹配
179 void Test7()
180 {
181     const int length = 7;
182     int preorder[length] = {1, 2, 4, 5, 3, 6, 7};
183     int inorder[length] = {4, 2, 8, 1, 6, 3, 7};
184     Test("Test7: for unmatched input", preorder, inorder, length);
185 }
186 
187 int main(int argc, char* argv[])
188 {
189     Test1();
190     Test2();
191     Test3();
192     Test4();
193     Test5();
194     Test6();
195     Test7();
196     return 0;
197 }

技术图片技术图片

 

技术图片             技术图片

  • 构建二叉树的两个函数:Construct()、ConstructCore()
  • Construct()面向输入数据(用户),ConstructCore()面向处理数据(程序)
  • 通过Construct()调用ConstructCore(),对用户隐藏了具体实现

BinaryTree.cpp

 1 #include <cstdio>
 2 #include "BinaryTree.h"
 3 
 4 BinaryTreeNode* CreateBinaryTreeNode(int value)
 5 {
 6     BinaryTreeNode* pNode = new BinaryTreeNode();
 7     pNode->m_nValue = value;
 8     pNode->m_pLeft = nullptr;
 9     pNode->m_pRight = nullptr;
10 
11     return pNode;
12 }
13 
14 void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight)
15 {
16     if(pParent != nullptr)
17     {
18         pParent->m_pLeft = pLeft;
19         pParent->m_pRight = pRight;
20     }
21 }
22 
23 void PrintTreeNode(const BinaryTreeNode* pNode)
24 {
25     if(pNode != nullptr)
26     {
27         printf("value of this node is: %d
", pNode->m_nValue);
28 
29         if(pNode->m_pLeft != nullptr)
30             printf("value of its left child is: %d.
", pNode->m_pLeft->m_nValue);
31         else
32             printf("left child is nullptr.
");
33 
34         if(pNode->m_pRight != nullptr)
35             printf("value of its right child is: %d.
", pNode->m_pRight->m_nValue);
36         else
37             printf("right child is nullptr.
");
38     }
39     else
40     {
41         printf("this node is nullptr.
");
42     }
43 
44     printf("
");
45 }
46 
47 void PrintTree(const BinaryTreeNode* pRoot)
48 {
49     PrintTreeNode(pRoot);
50 
51     if(pRoot != nullptr)
52     {
53         if(pRoot->m_pLeft != nullptr)
54             PrintTree(pRoot->m_pLeft);
55 
56         if(pRoot->m_pRight != nullptr)
57             PrintTree(pRoot->m_pRight);
58     }
59 }
60 
61 void DestroyTree(BinaryTreeNode* pRoot)
62 {
63     if(pRoot != nullptr)
64     {
65         BinaryTreeNode* pLeft = pRoot->m_pLeft;
66         BinaryTreeNode* pRight = pRoot->m_pRight;
67 
68         delete pRoot;
69         pRoot = nullptr;
70 
71         DestroyTree(pLeft);
72         DestroyTree(pRight);
73     }
74 }

BinaryTree.h

 1 struct BinaryTreeNode 
 2 {
 3     int                    m_nValue; 
 4     BinaryTreeNode*        m_pLeft;  
 5     BinaryTreeNode*        m_pRight; 
 6 };
 7 
 8 BinaryTreeNode* CreateBinaryTreeNode(int value);
 9 void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight);
10 void PrintTreeNode(const BinaryTreeNode* pNode);
11 void PrintTree(const BinaryTreeNode* pRoot);
12 void DestroyTree(BinaryTreeNode* pRoot);

 

 

以上是关于剑指Offer——面试题7:重建二叉树的主要内容,如果未能解决你的问题,请参考以下文章

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

剑指Offer:面试题07.重建二叉树

《剑指offer》第六题(重要!重建二叉树)

剑指offer——python第4题重建二叉树

剑指Offer面试题:07 重建二叉树

剑指Offer面试题:09 重建二叉树