从中序与后序遍历序列构造二叉树 最大二叉树 合并二叉树 二叉搜索树中的搜索
1.根据一棵树的中序遍历与后序遍历构造二叉树。
#include <bits/stdc++.h>
using namespace std;
struct TreeNode{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x)
{
val=x;
left=NULL;
right=NULL;
}
};
TreeNode* traversal(vector<int>& inorder,vector<int>& postorder)
{
if(postorder.size()==0)
return NULL;
int value=postorder[postorder.size()-1];
TreeNode* root=new TreeNode(value);
if(postorder.size()==1)
return root;
int index;
for(index=0;index<inorder.size();index++)
{
if(inorder[index]==value)
break;
}
vector<int> leftinorder(inorder.begin(),inorder.begin()+index);
vector<int> rightinorder(inorder.begin()+index+1,inorder.end());
postorder.resize(postorder.size()-1);
vector<int> leftpostorder(postorder.begin(),postorder.begin()+leftinorder.size());
vector<int> rightpostorder(postorder.begin()+leftinorder.size(),postorder.end());
root->left=traversal(leftinorder,leftpostorder);
root->right=traversal(rightinorder,rightpostorder);
return root;
}
TreeNode* buildTree(vector<int>& inorder,vector<int>& postorder)
{
if(inorder.size()==0||postorder.size()==0)
return NULL;
return traversal(inorder,postorder);
}
void print(TreeNode* root)
{
if(root==NULL)
return ;
queue<TreeNode*> que;
que.push(root);
while(!que.empty())
{
int size=que.size();
for(int i=0;i<size;i++)
{
TreeNode* node=que.front();
que.pop();
cout<<node->val<<" ";
if(node->left)
que.push(node->left);
if(node->right)
que.push(node->right);
}
cout<<endl;
}
}
int main()
{
vector<int> inorder={9,3,15,20,7};
vector<int> postorder={9,15,7,20,3};
TreeNode* root=buildTree(inorder,postorder);
print(root);
return 0;
}
思路:其实就是通过中序遍历(左中右),后序遍历(左右中),来将这棵二叉树还原输出,主要是怎么得到二叉树,在这里我们从根结点入手,后序遍历数组的末尾元素必定是整棵树的根结点,先将其确定,然后再通过遍历中序数组,来找其数组中与根节点相同的值,以其为分割点将中序数值分成左中序数组即用于寻找根结点的左子树,右中序数组即用于寻找根结点的右子树,分割完成后,要先将原后序数组的末尾元素舍去,再通过左中序数组的长度来分割后序数组,即左后序数组用于寻找根节点的左子树,右后序数组用于寻找根结点的右子树,最后通过层序遍历输出。
2.给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下:
- 二叉树的根是数组中的最大元素。
- 左子树是通过数组中最大值左边部分构造出的最大二叉树。
- 右子树是通过数组中最大值右边部分构造出的最大二叉树。
通过给定的数组构建最大二叉树,并且输出这个树的根节点。
#include <bits/stdc++.h>
using namespace std;
struct TreeNode{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x)
{
val=x;
left=NULL;
right=NULL;
}
};
TreeNode* construct(vector<int>& num)
{
TreeNode* node=new TreeNode(0);
if(num.size()==1)
{
node->val=num[0];
return node;
}
int maxval=0;
int index=0;
for(int i=0;i<num.size();i++)
{
if(num[i]>maxval)
{
maxval=num[i];
index=i;
}
}
node->val=maxval;
if(index>0)
{
vector<int> new1(num.begin(),num.begin()+index);
node->left=construct(new1);
}
if(index<num.size()-1)
{
vector<int> new2(num.begin()+index+1,num.end());
node->right=construct(new2);
}
return node;
}
int main()
{
vector<int> num={3,2,1,6,0,5};
TreeNode* node=construct(num);
cout<<node->val;
return 0;
}
思路:对于这道题我们要清楚最大二叉树是什么,即根结点为数组中最大元素,找到后,将其分割为左右2个区域,左区域再找最大值作为左子树的根结点,右区域找最大值作为右子树的根结点,依次循环直到遍历结束。
如果数组长度为1,那么只有1个元素且为根结点,返回即可。如果不是我们要找数组中的最大值作为根结点,其下表为index,根据index来分割左右区域,默认区间左闭右开,左区域区间为(num.begin(),num.begin()+index),右区域区间为(num.begin()+index+1,num.end()),找到区间后再进行递归分别构造左右子树,最终能够将整颗二叉树构造完成。
3.给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。
#include <bits/stdc++.h>
using namespace std;
struct TreeNode{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x)
{
val=x;
left=NULL;
right=NULL;
}
};
TreeNode* mergeTree(TreeNode* t1,TreeNode* t2)
{
if(t1==NULL)
return t2;
if(t2==NULL)
return t1;
TreeNode* root=new TreeNode(0);
root->val=t1->val+t2->val;
root->left=mergeTree(t1->left,t2->left);
root->right=mergeTree(t1->right,t2->right);
return root;
}
void print(TreeNode* root)
{
if(root==NULL)
return ;
queue<TreeNode*> que;
que.push(root);
while(!que.empty())
{
int size=que.size();
for(int i=0;i<size;i++)
{
TreeNode* node=que.front();
que.pop();
cout<<node->val<<" ";
if(node->left)
que.push(node->left);
if(node->right)
que.push(node->right);
}
cout<<endl;
}
}
int main()
{
TreeNode* t1=new TreeNode(1);
t1->left=new TreeNode(3);
t1->right=new TreeNode(2);
t1->left->left=new TreeNode(5);
TreeNode* t2=new TreeNode(2);
t2->left=new TreeNode(1);
t2->right=new TreeNode(3);
t2->left->right=new TreeNode(4);
t2->right->right=new TreeNode(7);
TreeNode* root=mergeTree(t1,t2);
print(root);
return 0;
}
思路:这里我们要清楚,再遍历时是同步遍历的2棵树,当遍历t1根结点的左孩子时,也相应地正在遍历t2根结点地左孩子,如果t1结点为空就返回t2,如果t2结点为空就返回t1,同时也将两者都为空的情况包还在内了就是返回空,我们定义一棵新的二叉树,如果遍历的t1和t2结点不为空就返回它们的和给到新的二叉树的对应位置,依次循环即可。
4.给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。
#include <bits/stdc++.h>
using namespace std;
struct TreeNode{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x)
{
val=x;
left=NULL;
right=NULL;
}
};
TreeNode* search(TreeNode* root,int target)
{
if(root==NULL)
return root;
while(!NULL)
{
if(target>root->val)
root=root->right;
else if(target<root->val)
root=root->left;
else
return root;
}
}
void print(TreeNode* root)
{
if(root==NULL)
return ;
queue<TreeNode*> que;
que.push(root);
while(!que.empty())
{
int size=que.size();
for(int i=0;i<size;i++)
{
TreeNode* node=que.front();
que.pop();
cout<<node->val<<" ";
if(node->left)
que.push(node->left);
if(node->right)
que.push(node->right);
}
cout<<endl;
}
}
int main()
{
TreeNode* root=new TreeNode(4);
root->left=new TreeNode(2);
root->right=new TreeNode(7);
root->left->left=new TreeNode(1);
root->left->right=new TreeNode(3);
root->right->right=new TreeNode(8);
TreeNode* node=search(root,2);
print(node);
return 0;
}
思路:首先我们要清楚二叉搜索树是有顺序的,即根结点的值大于其左子树的所有值,小于其右子树的所有值,对于其左右子树也满足这个规律,这里我们使用迭代法比较容易,只要根不为空,就进行遍历,搜索值大于结点的值就向右遍历,小于就向左遍历,等于就输出以此结点为根结点的子树。