剑指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 }