劍指Offer面試題6 重建二叉樹
阿新 • • 發佈:2018-12-21
題目:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入的前序遍歷序列{1,2,4,7,3,5,6,8}和後序遍歷序列{4,7,2,1,5,3,8,6},則重建出如圖所示的二叉樹
二叉樹結點定義如下:
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
題目分析:二叉樹的前序遍歷順序是根左右,第一個數為根的值。中序遍歷順序是左根右,根結點的值在序列中間。因此當我們遍歷中序遍歷找到根結點的值的位置,根結點位置前的數字為左子樹結點的值,根結點位置後的數字為右子樹結點的值。這樣我們就可以找到左右子樹的前序遍歷和中序遍歷序列,接下來可以用同樣的方法用遞迴去構建左右子樹。
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,inorder,preorder+length-1,inorder+length-1); } BinaryTreeNode* ConstructCore(int* startPreorder,int* endPreorder,int* startInorder,int* endInorder) { //前序遍歷序列的第一個數字是根結點的值 int rootValue = startInorder[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 cout << "invalid input."; } //在中序遍歷中找到根結點的值 int* rootInorder = startInorder; while(rootInorder <= endInorder && *rootInorder != rootValue) ++rootInorder; if(rootInorder == endInorder && *rootInorder != rootValue) cout << "invalid input."; 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; }