要唯一确定一颗二叉树,必须已知中序(先序,中序,后序之间)
1:先序与中序建树(采用递归)
思想:1)根据先序确定根节点位置。
2)根据根节点在中序序列的位置划分出二叉树的左右子树包含哪些结点
3)对左右子树递归上述步骤,直到数组为空。
node *creat(int prel,int prer,int inl,int inr){
if(prel>prer){
return NULL;
}
node *root=new node;
root->data=pre[prel];
int k;
for( k=inl;k<=inr;k++){
if(in[k]==pre[prel])
break;
}
int leftnum=k-inl;
root->lchild =creat(prel+1,prel+leftnum,inl,k-1); //下标要写对哦
root->rchild =creat(prel+leftnum+1,prer,k+1,inr);
return root;
}
2:中序与后序建树
仿照先序与中序遍历,容易改写代码得到
node *creat(int postl,int postr,int inl,int inr){
if(postl>postr){
return NULL;
}
node *root=new node;
root->data=post[postr];
int k;
for( k=inl;k<=inr;k++){
if(in[k]==post[postr])
break;
}
int leftnum=k-inl;
root->lchild =creat(postl,postl+leftnum-1,inl,k-1);
root->rchild =creat(postl+leftnum,postr-1,k+1,inr);
return root;
}
2:先序与后序建树输出一组中序(树不唯一)
已知二叉树的前序和后序是无法唯一确定一颗二叉树的,因为可能会存在多种情况,这种情况就是一个结点可能是根的左孩子也有可能是根的右孩子,如果发现了一个无法确定的状态,置flag = 0,此处输出一个方案中序遍历方案,可以假定这个不可确定的孩子的状态是右孩子,接下来的问题是如何求根结点和左右孩子划分的问题了,首先我们需要知道树的表示范围,需要四个变量,分别是前序的开始的地方prel,前序结束的地方prer,后序开始的地方postl,后序结束的地方postr,前序的开始的第一个应该是后序的最后一个是相等的,这个结点就是根结点,以后序的根结点的前面一个结点作为参考,寻找这个结点在前序的位置,就可以根据这个位置来划分左右孩子,递归处理
void fun(int preleft,int preright,int postleft,int postright){
if(preleft==preright){//递归边界
in.push_back(pre[preleft]);
return ;
}
if(pre[preleft]==post[postright]){
int i=preleft+1;
while(i<=preright && pre[i]!=post[postright-1]) i++;
if(i-preleft>1)
fun(preleft+1,i-1,postleft,postleft+i-2-preleft);
else
flag=true;
in.push_back(post[postright]);
fun(i,preright,postleft+i-1-preleft,postright-1);
}
}
最近祖先结点LCA(递归算法)
前提:查找结点u,v存在于二叉树
分析,最近要不是根结点,要不是根节点左子树中某一结点,要不是根节点右子树中某一结点!!
思想:1)空树直接return NULL
2)若俩结点之一为根节点,直接return root,否则,对当前结点的左右子树进行递归1,2步,再对递归出口结果进行判断即可
node *LCA(node *root, int u, int v) { //查找两节点最近祖先
if (root == NULL) return NULL;
if (root->data== u || root->data== v) return root;
node *left =LCA(root->lchild,u,v);
node *right = LCA(root->rchild,u,v);
if (left && right ) return root; //u,v分别位于左右子树的情况
return left == NULL ? right : left;
}