实现遍历构造二叉树:
理论可见:
关于他的代码实现:z
由前序遍历和中序遍历构造二叉树
解题思路
-
前序遍历的
第一个值即为根节点的值; -
两种遍历的左右子树大小一样,因此可以在
中序遍历中找到根节点的值,则其左侧即为左子树,右侧即为右子树
此时左子树的大小已经得到,右子树的大小可以通过整个树的大小及左子树的大小运算得到; -
递归构建左右子树即可.
时间复杂度:O(n), n为元素个数。 空间复杂度:O(n)
参考:链接
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize){
if(preorderSize== 0||inorderSize== 0) //前序遍历长度、中序遍历长度=0
return NULL;
struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode)); //申请一个二叉树root指针
int index; //此时下标
root -> val = preorder[0];//root指针数据指向前序遍历的第一个元素即根节点
for(index = 0;index < inorderSize;index++)//index<中序遍历的长度 递归
{ if(inorder[index]==preorder[0]) //中序遍历里面找到根结点 左边为左子树,右边为右子树
break; }
root->left=buildTree(preorder+1,index,inorder,index);
root->right=buildTree(preorder+index+1,preorderSize-index-1,inorder+index+1,preorderSize-index-1);
return root;
}
这里主要讲下这二句:
root->left=buildTree(preorder+1,index,inorder,index);
root->right=buildTree(preorder+index+1,preorderSize-index-1,inorder+index+1,preorderSize-index-1);
举个例子说明过程吧:
输入
-
preorder = [3,9,20,15,7]
-
inorder =[9,3,15,20,7]
-
root -> val = preorder[0];前序找到根节点是3
-
- 再通过for循环找到了根节点3在中序遍历的位置 是index=1时候,第二个数组元素
-
root->left=buildTree(preorder+1,index,inorder,index);。左边的子树要递归的子树此时的范围是函数(下一个前序的元素,1,inorder,1) ,即preorder=[9],inorder=[9],再递归调用函数。
等于递归左子树的了。
-
4.比如第一次得到根节点3,index=1时候。
root->right=buildTree(preorder+index+1,preorderSize-index-1,inorder+index+1,preorderSize-index-1);
右边的子树要递归的函数(前序+index+1,前序长度5-index-1,后序+index+1, 前序长度5-index-1)
此时前序preorder=[20,15,7],inorder=[15,20,7]。
等于递归右子树的了。
由后序遍历和中序遍历构造二叉树
解题思路
跟上面的一样,先通过后序找到根结点,然后再递归左右子树。
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
struct TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int postorderSize){
if(postorderSize== 0||inorderSize== 0) //前序遍历长度、中序遍历长度=0
return NULL;
struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode)); //申请一个二叉树root指针
int index; //此时下标
root -> val = postorder[postorderSize-1];//root指针数据指向后序遍历的最后一个元素即根节点
for(index = 0;index < inorderSize;index++)//index<中序遍历的长度 递归
{ if(inorder[index]==postorder[postorderSize-1]) //中序遍历里面找到根结点 左边为左子树,右边为右子树
break; }
root->left=buildTree(inorder,index,postorder,index);
root->right=buildTree(inorder+index+1,inorderSize-index-1,postorder+index,inorderSize-index-1);
return root;
}
ok,结合着第一个理解一下
由层次遍历和中序遍历构造二叉树
解题思路
-
层序遍历序列:D A B E F C G H I
-
中序遍历序列:E A F D H C B G I
根据层次遍历先找到根结点、在匹配中序,递归调用左右子树
比如D根结点。在中序中找到他,前面的EAF是左子树,在递归函数左子树
代码
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
//因为层序是先输出根节点的,所以可以递归查找
string s1,s2;
void find(int l1,int r1,int l2,int r2)
{
int i,j;
for(i=l2;i<=r2;i++)//找层次遍历中优先输出根节点的位置
{
int f=0;
for(j=l1;j<=r1;j++)
{
if(s2[i]==s1[j])//输出根节点
{
cout<<s1[j];
f=1;
break;
}
}
if(f)//如果f不为0,说明找到了,break;
break;
}
//此时DBEAC ABCDE
//此时跟结点A遍历中序,j=数组3位置 A 也就是l1+3
if(j>l1) //如果j>0 也就是一次一次递归,左子树结点会越来越接近0位置
find(l1,j-1,0,r2);//遍历左子树
if(j<r1) //如果j<r1最大长度 也就是一次一次递归,右子树结点会越来越接近r1位置
find(j+1,r1,0,r2);//遍历右子树
}
int main()
{
cin>>s1>>s2;
find(0,s1.length()-1,0,s2.length());
return 0;
}
上面基本实现了二二遍历实现构造二叉树