若树为空树,那么返回;
若不为空,则先递归翻转左右子树,然后再将左右子树的结点互换。
void revert(int root){
if (root == -1){
return;
}
revert(nodes[root].left);
revert(nodes[root].right);
swap(nodes[root].left,nodes[root].right);
}
两个序列一个提供根结点,另一个用来划分左右子树
以先序中序还原二叉树为例,先序的第一个元素为该树的根结点,通过该根结点的编号,便可以将中序和先序的元素划分左右子树。左右子树的根结点就是该树的左右结点,同时该树的根结点又有可能是其父亲结点的左右孩子。
#include
#include
using namespace std;
vector pre,in_;
const int N = 55;
struct binaryTree{
int left;
int right;
}nodes[N];
int buildTree(int preL,int preR,int inL,int inR){
/*
整个思路很简单,通过先序序列找出该子树的根结点
然后根据中序序列通过根结点root再将子树分为左子树和右子树。
返回根结点
*/
if (preL > preR)return -1;
int root = pre[preL];
int rootindexofin;//找到root在中序序列中的位置
for (int i=inL;i<=inR;i++){
if (in_[i] == root){
rootindexofin = i;
break;
}
}
// root的左子节点就是其左子树的根结点,反之其也可能是其父亲结点的左子节点/右子节点
int countof_LeftTree = rootindexofin - inL;//其左子树的结点数
nodes[root].left = buildTree(preL+1,preL+countof_LeftTree,inL,rootindexofin-1);
nodes[root].right = buildTree(preL+countof_LeftTree+1,preR,rootindexofin+1,inR);
return root;
}
vector post;
void postorder(int root){
if (root==-1)return;
postorder(nodes[root].left);
postorder(nodes[root].right);
post.push_back(root);
}
int main(){
int n;
scanf("%d",&n);
for (int i=0;i
后序中序还原二叉树,后序序列,那么每个根结点就是其最后一个元素,后面的思路相同。
#include
#include
#include
using namespace std;
vector in_,pre,post;
const int N = 60;
struct binaryTree{
int left;
int right;
}nodes[N];
int buildTree(int postL,int postR,int inL,int inR){
if (postL>postR)return -1;
int root = post[postR];
int rootindexofin;
for (int i=inL;i<=inR;i++){
if (in_[i] == root){
rootindexofin = i;
break;
}
}
int countleftTree = rootindexofin - inL;
nodes[root].left = buildTree(postL,postL+countleftTree-1,inL,rootindexofin-1);
nodes[root].right = buildTree(postL+countleftTree,postR-1,rootindexofin+1,inR);
return root;
}
void preorder(int root){
if (root == -1)return;
pre.push_back(root);
preorder(nodes[root].left);
preorder(nodes[root].right);
}
int main(){
int n;
scanf("%d",&n);
for (int i=0;i
层序中序还原二叉树:思路一样,层序序列无法像前面两个可以简单地分开左右子树的元素,因而需要重新筛检左右子树的元素,重新使用vector进行组合,按照层序序列的顺序筛完,第一个元素总是该树的根结点。
#include
#include
#include
using namespace std;
const int N = 60;
vector pre,in_,layer;
struct binaryTree{
int left;
int right;
}nodes[N];
int isleft[N];
int buildTree(vector layer,int inL,int inR){
memset(isleft,0,sizeof isleft);
if (layer.size()==0)return -1;
int root = layer[0];
int rootindexofin;
for (int i=inL;i<=inR;i++){
if (in_[i] == root){
rootindexofin = i;
break;
}else {
isleft[in_[i]] = 1;
}
}
vector leftTree;
vector rightTree;
for (int i=1;i
1.终止条件:
if (root == -1)return -1;//此时root == -1已经为叶子结点,未找到 p和q,返回-1
// 找到p和q返回p和q
if (root == p) return p;
if (root == q) return q;
左右地递归:返回左右子树的结果:
int left = LCA(nodes[root].left,p,q);
int right = LCA(nodes[root].right,p,q);
接下来的判断才是重要的:
我们现在处在root这个树这里,根据左右子树寻找的结果来返回最近的公共祖先
现在返回的值要么是-1(表示未寻找到p和q)和截止至root这个位置的最近公共祖先的结点的数值。
1. p,q在root分别存在于root的左右子树中(异侧)——>root即为最近祖先节点
if (left != -1 && right != -1){
return root;
}
2. p, q均在root的左侧——>p/q即为最近祖先节点
那么right == 1而left !=-1,由于是最近公共结点,此时的left值便是最近。
else if (left != -1){
return left;
}
3. p, q均在root的右侧——>同理
else if (right != -1){
return right;
}