题目
从前序与中序遍历序列构造二叉树
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/
15 7
法一:递归
思路
根据前序遍历可以知道根节点,根据根节点可以在中序序列中得到左子树 和 右子树 的中序序列
我们可以得到如下信息:
- 先序序列------根节点的值
- 中序序列------根节点所在的下标
- 中序序列-----左子树的长度
- 中序序列-----右子树的长度

代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <map>
#include <list>
using namespace std;
struct TreeNode
{
int data;
TreeNode * left;
TreeNode * right;
TreeNode(int value)
{
data = value;
left = NULL;
right = NULL;
}
};
// 层序输出构建的二叉树
void PrintFromTopToBottom(TreeNode * root)
{
if(root == NULL)
{
return;
}
list<TreeNode *> l;
l.push_back(root);
while(!l.empty())
{
TreeNode * temp = l.front();
cout << temp->data << " ";
l.pop_front();
if(temp->left)
{
l.push_back(temp->left);
}
if(temp->right)
{
l.push_back(temp->right);
}
}
cout << endl;
}
map<int , int> index; // 存储中序遍历----数据 vs 下标
// 递归
// 根据前序遍历可以知道根节点,根据根节点可以在中序序列中得到左子树 和 右子树 的中序序列
TreeNode * MyBuildTree(const vector<int> & preorder , const vector<int> & inorder , int preOrder_left , int preOrder_right , int inOrder_left , int inOrder_right)
{
int size = preorder.size();
// 可根据数据去知道下标
for(int i = 0; i < size;++i)
{
index[inorder[i]] = i;
}
if(preOrder_left > preOrder_right)
{
return NULL;
}
// 先序遍历中根节点的下标
int preOrder_root = preOrder_left;
// 根节点的值
int root_value = preorder[preOrder_root];
TreeNode * root = new TreeNode(root_value);
// 中序遍历中根节点的下标
int inOrder_root = index[root_value];
// 得到左子树的节点数目
int size_left_subtree = inOrder_root - inOrder_left;
// 先序遍历下标 根 左 右
// 先序遍历 preOrder_left preOrder_left + size_left_subtree preOrder_right
// 中序遍历下标 左 根 右
// 中序遍历 inOrder_left inOrder_root inOrder_right
// 递归构造左子树,并连接到左节点
root->left = MyBuildTree(preorder , inorder , preOrder_left + 1 , preOrder_left + size_left_subtree , inOrder_left , inOrder_root - 1);
// 递归构造右子树,并连接到右节点
root->right = MyBuildTree(preorder , inorder , preOrder_left + size_left_subtree + 1 , preOrder_right , inOrder_root + 1 , inOrder_right);
return root;
}
// 递归
TreeNode * BuildTree(const vector<int> & preorder ,const vector<int> & inorder)
{
if(preorder.empty())
{
return NULL;
}
int size = preorder.size();
// 可根据数据去知道下标
for(int i = 0; i < size;++i)
{
index[inorder[i]] = i;
}
return MyBuildTree(preorder , inorder , 0 , size - 1 , 0 , size -1);
}
int main()
{
vector<int> preOrder;
preOrder.push_back(8);
preOrder.push_back(4);
preOrder.push_back(9);
preOrder.push_back(12);
preOrder.push_back(2);
preOrder.push_back(1);
preOrder.push_back(5);
vector<int> inOrder;
inOrder.push_back(9);
inOrder.push_back(4);
inOrder.push_back(12);
inOrder.push_back(8);
inOrder.push_back(1);
inOrder.push_back(2);
inOrder.push_back(5);
TreeNode * root = BuildTree(preOrder , inOrder);
PrintFromTopToBottom(root);
return 0;
}
采用层序遍历输出我们构建的二叉树,输出结果如下:
8 4 2 9 12 1 5
该博客介绍了如何利用LeetCode的第105题,通过给定的前序和中序遍历序列来构建二叉树。文中详细解释了递归方法的思路,即根据前序遍历确定根节点,然后在中序遍历中找到根节点的位置,从而划分左右子树,并继续递归构建。最后展示了构建完成的二叉树的层序遍历结果。

2818

被折叠的 条评论
为什么被折叠?



