【面试题006】重建二叉树
重建二叉树,
在前序遍历和中序遍历两个序列中,确定了根结点的值,进而分别找到了左右子树对应的序列;
递归的构建二叉树。
ConstructBinaryTree.cpp:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
#include <iostream>
#include <exception> #include <cstdio> #include "BinaryTree.h" using namespace std; BinaryTreeNode *ConstructCore( int *startPreorder, int *endPreorder, int *startInorder, int *endInorder); BinaryTreeNode *Construct(int *preorder, int *inorder, int length) { if(preorder == NULL || inorder == NULL || length <= 0) return NULL; return ConstructCore(preorder, preorder + length - 1, inorder, inorder + length - 1); } BinaryTreeNode *ConstructCore ( int *startPreorder, int *endPreorder, int *startInorder, int *endInorder ) { // 前序遍历序列的第一个数字是根结点的值 int rootValue = startPreorder[0]; BinaryTreeNode *root = new BinaryTreeNode(); root->m_nValue = rootValue; root->m_pLeft = root->m_pRight = NULL; if(startPreorder == endPreorder) { if(startInorder == endInorder && *startPreorder == *startInorder) return root; else throw std::exception(); } // 在中序遍历中找到根结点的值 int *rootInorder = startInorder; while(rootInorder <= endInorder && *rootInorder != rootValue) ++ rootInorder; if(rootInorder == endInorder && *rootInorder != rootValue) throw std::exception(); int leftLength = rootInorder - startInorder; int *leftPreorderEnd = startPreorder + leftLength; if(leftLength > 0) { // 构建左子树 root->m_pLeft = ConstructCore(startPreorder + 1, leftPreorderEnd, startInorder, rootInorder - 1); } if(leftLength < endPreorder - startPreorder) { // 构建右子树 root->m_pRight = ConstructCore(leftPreorderEnd + 1, endPreorder, rootInorder + 1, endInorder); } return root; } // 普通二叉树 // 1 // / // 2 3 // / / // 4 5 6 // / // 7 8 int main() { const int length = 8; int preorder[length] = {1, 2, 4, 7, 3, 5, 6, 8}; int inorder[length] = {4, 7, 2, 1, 5, 3, 8, 6}; printf("The preorder sequence is: "); for(int i = 0; i < length; ++ i) printf("%d ", preorder[i]); printf(" "); printf("The inorder sequence is: "); for(int i = 0; i < length; ++ i) printf("%d ", inorder[i]); printf(" "); try { BinaryTreeNode *root = Construct(preorder, inorder, length); PrintTree(root); DestroyTree(root); } catch(std::exception &exception) { printf("Invalid Input. "); } return 0; } |
运行结果:
The preorder sequence is: 1 2 4 7 3 5 6 8
The inorder sequence is: 4 7 2 1 5 3 8 6
value of this node is: 1
value of its left child is: 2.
value of its right child is: 3.
value of this node is: 2
value of its left child is: 4.
right child is null.
value of this node is: 4
left child is null.
value of its right child is: 7.
value of this node is: 7
left child is null.
right child is null.
value of this node is: 3
value of its left child is: 5.
value of its right child is: 6.
value of this node is: 5
left child is null.
right child is null.
value of this node is: 6
value of its left child is: 8.
right child is null.
value of this node is: 8
left child is null.
right child is null.
BinaryTree.h:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#ifndef _BINARY_TREE_H_
#define _BINARY_TREE_H_ struct BinaryTreeNode { int m_nValue; BinaryTreeNode *m_pLeft; BinaryTreeNode *m_pRight; }; BinaryTreeNode *CreateBinaryTreeNode(int value); void ConnectTreeNodes( BinaryTreeNode *pParent, BinaryTreeNode *pLeft, BinaryTreeNode *pRight); void PrintTreeNode(BinaryTreeNode *pNode); void PrintTree(BinaryTreeNode *pRoot); void DestroyTree(BinaryTreeNode *pRoot); #endif /*_BINARY_TREE_H_*/ |
BinaryTree.cpp:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
#include <iostream> #include <cstdio> #include "BinaryTree.h" using namespace std; BinaryTreeNode *CreateBinaryTreeNode(int value) { BinaryTreeNode *pNode = new BinaryTreeNode(); pNode->m_nValue = value; pNode->m_pLeft = NULL; pNode->m_pRight = NULL; return pNode; } void ConnectTreeNodes(BinaryTreeNode *pParent, BinaryTreeNode *pLeft, BinaryTreeNode *pRight) { if(pParent != NULL) { pParent->m_pLeft = pLeft; pParent->m_pRight = pRight; } } void PrintTreeNode(BinaryTreeNode *pNode) { if(pNode != NULL) { printf("value of this node is: %d ", pNode->m_nValue); if(pNode->m_pLeft != NULL) printf("value of its left child is: %d. ", pNode->m_pLeft->m_nValue); else printf("left child is null. "); if(pNode->m_pRight != NULL) printf("value of its right child is: %d. ", pNode->m_pRight->m_nValue); else printf("right child is null. "); } else { printf("this node is null. "); } printf(" "); } void PrintTree(BinaryTreeNode *pRoot) { PrintTreeNode(pRoot); if(pRoot != NULL) { if(pRoot->m_pLeft != NULL) PrintTree(pRoot->m_pLeft); if(pRoot->m_pRight != NULL) PrintTree(pRoot->m_pRight); } } void DestroyTree(BinaryTreeNode *pRoot) { if(pRoot != NULL) { BinaryTreeNode *pLeft = pRoot->m_pLeft; BinaryTreeNode *pRight = pRoot->m_pRight; delete pRoot; pRoot = NULL; DestroyTree(pLeft); DestroyTree(pRight); } } |
Makefile:
1
2 3 4 5 6 7 8 9 10 11 12 |
.PHONY:clean
CPP=g++ CFLAGS=-Wall -g BIN=test OBJS=ConstructBinaryTree.o BinaryTree.o LIBS= $(BIN):$(OBJS) $(CPP) $(CFLAGS) $^ -o $@ $(LIBS) %.o:%.cpp $(CPP) $(CFLAGS) -c $< -o $@ clean: rm -f *.o $(BIN) |