《剑指Offer》学习笔记--面试题6:重建二叉树
2015-05-05 11:35
633 查看
题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不重复的数字。例如输入前序遍历序列{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;
};
解题思路:在二叉树的前序遍历序列中,第一个数字总是树的根结点的值。但在中序序列中,根结点的值在序列的中间,左子树的结点的值位于根节点的值的左边,而右子树的结点的值位于根结点的值的右边。因此我们需要扫描中序遍历序列,才能找到根结点的值。
在想清楚如何在前序遍历和中序遍历的序列中确定左、右子树的子序列之后,我们可以写出如下的递归代码:
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
解题思路:在二叉树的前序遍历序列中,第一个数字总是树的根结点的值。但在中序序列中,根结点的值在序列的中间,左子树的结点的值位于根节点的值的左边,而右子树的结点的值位于根结点的值的右边。因此我们需要扫描中序遍历序列,才能找到根结点的值。
在想清楚如何在前序遍历和中序遍历的序列中确定左、右子树的子序列之后,我们可以写出如下的递归代码:
#include <iostream> using namespace std; typedef struct BinaryTreeNode{ int data; struct BinaryTreeNode* lchild; struct BinaryTreeNode* rchild; }; 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 ) { //前序遍历序列第一个数字是根结点的值 BinaryTreeNode* root = new BinaryTreeNode(); int rootValue = startPreorder[0]; root->data = rootValue; root->lchild = root->rchild = NULL; if(startPreorder == endPreorder){ if(startInorder == endInorder && *startPreorder == *startInorder)//只有一个节点了 return root; else throw std::exception("Invalid input."); } //在中序遍历中找到根结点的值 int *rootInorder = startInorder; while(rootInorder <= endInorder && *rootInorder != rootValue){ ++rootInorder; } if(rootInorder == endInorder && *rootInorder != rootValue){ throw std::exception("Invalid input."); } int leftLength = rootInorder - startInorder; int *leftPreorderEnd = startPreorder + leftLength; if(leftLength > 0){ //构建左子树 root->lchild = ConstructCore(startPreorder+1, leftPreorderEnd, startInorder, rootInorder-1); } if(leftLength < endPreorder - startPreorder){ //构建右子树 root->rchild = ConstructCore(leftPreorderEnd+1, endPreorder, rootInorder+1, endInorder); } return root; } //打印出构建后二叉树的后序遍历序列 void PrintLorder(BinaryTreeNode *root) { if(root != NULL){ PrintLorder(root->lchild); PrintLorder(root->rchild); cout<<root->data<<" "; } } int main() { int preOrder[] = {1,2,4,7,3,5,6,8}; int inOrder[] = {4,7,2,1,5,3,8,6}; int length = sizeof(preOrder)/sizeof(int); BinaryTreeNode *root = Construct(preOrder, inOrder, length); PrintLorder(root); system("pause"); return 0; }在函数ConstrucCore中,我们先根据前序遍历序列的第一个数字创建根结点,接下来在中序序列中找出根结点的位置,这样就能确定左、右子树结点的数量。在前序遍历和中序遍历的序列中划分了左、右子树结点的值之后,我们就可以递归地调用函数ConstructCore,分别构建它的左右子树。
相关文章推荐
- 《剑指Offer》学习笔记--面试题23:从上往下打印二叉树
- 《剑指Offer》学习笔记--面试题60:把二叉树打印出多行
- 《剑指Offer》学习笔记--面试题61:按之字形顺序打印二叉树
- 《剑指Offer》学习笔记--面试题25:二叉树中和为某一直的路径
- 《剑指Offer》学习笔记--面试题58:二叉树的下一个结点
- 《剑指Offer》学习笔记--面试题39:二叉树的深度
- 《剑指Offer》学习笔记--面试题62:序列化二叉树
- 《剑指Offer》学习笔记--面试题59:对称的二叉树
- 剑指Offer学习之面试题6 :重建二叉树
- 《剑指Offer》学习笔记--面试题28:字符串的排列
- 《剑指Offer》学习笔记--面试题30:最小的k个数
- 《剑指Offer》学习笔记--面试题35:第一个只出现一次的字符
- 《剑指Offer》学习笔记--面试题55:字符流中第一个不重复的字符
- 《剑指Offer》学习笔记--面试题3:二维数组中的查找
- 剑指offer面试题7:重建二叉树 Java代码实现
- 《剑指Offer》学习笔记--面试题12:打印1到最大的n位数
- 剑指Offer(第二版)面试题7:重建二叉树
- 《剑指Offer》学习笔记--面试题31:连续子数组的最大和
- 《剑指Offer》学习笔记--面试题34:丑数
- 《剑指Offer》学习笔记--面试题64:数据流中的中位数