二叉树的最近公共祖先

提示:马行千里 不洗尘沙

文章目录

  • 找到公共祖先
    • 思路
    • 递归
    • 迭代
    • 运行截图
  • 可执行


找到公共祖先

二叉树的最近公共祖先_第1张图片
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3

思路

看到这个题目 我的第一个想法就是与后序遍历 若是使用栈 当处理到这个结点的时候 栈中剩余结点就是它的祖先,若是使用递归自然也是选择后序遍历 以为后序遍历本身就是回溯的,若是我们在回溯的过程中发现一个结点左子树含有p或者q 右子树也含有p 或者q 此时就是最近公共祖先 此时直接返回便可

递归

BiTree* PastFindAncient(BiTree* T){
	BiTree* left=NULL;BiTree* right=NULL;
	if(T->Lchild==NULL&&T->Rchild==NULL||T->data==val1||T->data==val2){
		if(T->data==val1||T->data==val2){
			return T;
		}
		else{
			return NULL;
		}
	}
	if(T->Lchild){
		left=PastFindAncient(T->Lchild);
	}
	if(T->Rchild){
		right=PastFindAncient(T->Rchild);
	}
	if(left&&right){//此时说明找到了 
		cout<<"此时找到了结点"<<T->data<<"便是公共祖先"<<endl;
		return T; 
	}
	else if(left){
		return left;
	}
	else if(right){
		return right;
	}
	else{
		return NULL;
	}
}

迭代

迭代中不过将之前的处理函数visit 换成这里的栈中元素保存的语句 因为我们知道后序遍历过程中当你要处理某一个结点的时候 此时栈中存放的后面带一个NULL的结点就是它的祖先 比如我们这里所写的6 的祖先是7 10 8 而5的祖先是7 10 8 其中如何把第一个中的五去掉然后再处理便可,就得到了到此结点的路径,然后判断路径重合的部分即可确定最近公共结点 但是本题中依然可以使用其他的方式就是直接再栈中处理,放入两个栈中 先将长栈多余的弹出,然后一样长的时候 开始都弹 直到第一个相等的就是公共结点(因为从根结点到公共结点的路径是一样的 所以从同样长度开始弹)

BiTree* RePastFindAncient(BiTree* T){
	stack<BiTree*> S;
	stack<BiTree*> S1,S2,S3,S4;
	if(T==NULL)  return NULL;
	S.push(T);
	while(!S.empty()){
		T=S.top();
		if(T==NULL){
			S.pop(); 
			T=S.top();
			if(T->data==val1){//此时栈中后面跟一个NULL便是祖先 
				while(!S.empty()){
					BiTree* cur=S.top();
					S.pop();
					result1.push_back(cur); 
					S2.push(cur); 
				}//将S中中元素倒入S1,S2中
				while(!S2.empty()){//再将S2中元素倒回 
					BiTree* cur=S2.top();
					S2.pop();
					S.push(cur);; 
				} 
			}
			if(T->data==val2){//此时栈中都是后发现元素的祖先,与上相同操作 
				while(!S.empty()){
					BiTree* cur=S.top();
					S.pop();
					result2.push_back(cur);
					S4.push(cur); 
				}//将S中中元素倒入S3,S4中
				while(!S4.empty()){//再将S2中元素倒回 
					BiTree* cur=S4.top();
					S4.pop();
					S.push(cur);; 
				} 				
			} 
			S.pop();
		} 
		else{
			S.pop();
			S.push(T);
			S.push(NULL); 
			if(T->Rchild)S.push(T->Rchild);
			if(T->Lchild)S.push(T->Lchild);	
		}
	} 
	BiTree* cur=NULL;
	reverse(result1.begin(),result1.end());
	reverse(result2.begin(),result2.end());
	cout<<"向量一是"<<endl;
	for(int i=0;i<result1.size();i++){
		if(result1[i]!=NULL){
			cout<<result1[i]->data<<" ";
		}
		else{
			cout<<"NULL"<<" ";
		}
	}cout<<endl; 
	cout<<"向量二是"<<endl;
	for(int i=0;i<result2.size();i++){
		if(result2[i]!=NULL){
			cout<<result2[i]->data<<" ";
		}
		else{
			cout<<"NULL"<<" "; 
		}
	}cout<<endl;
	for(int i=0;i<result1.size()&&i<result2.size();i++){
		if(result2.size()<result1.size()){
			if(result1[i]==result2[i]&&result1[i]!=NULL&&result1[i+1]==NULL){
			cur=result1[i];}
		}
		else{
			if(result1[i]==result2[i]&&result1[i]!=NULL&&result2[i+1]==NULL){
			cur=result1[i];}
		}
	}
	return cur;
}

运行截图

二叉树的最近公共祖先_第2张图片

二叉树的最近公共祖先_第3张图片
通过这个截图你会发现,后序遍历中,其中栈中存储的并不都是祖先,但是祖先却也能分离处理 结点之后跟一个NULL便是此时这个结点的祖先, 但是这里我们要找的是包含本结点的前驱 所以也就意味着最后一可能不为NULL 比如这里的5 就不是6的祖先

可执行

#include
typedef struct BiTree{
	int data;
	BiTree* Lchild=NULL;
	BiTree* Rchild=NULL; 
}BiTree;
typedef struct Node{
	BiTree *T;
	int sum=0;
}Node;
using namespace std;
int X;int val1;int val2;
vector<BiTree*> result1,result2;
void PreCreatTree(BiTree* &T){//前序创造一个树 
	int input;cin>>input;
	if(input==-1){
		T=NULL;
	}
	else{
		T=(BiTree*)malloc(sizeof(BiTree));
		T->data=input;
		PreCreatTree(T->Lchild);
		PreCreatTree(T->Rchild);
	}
}
void PreTravel(BiTree* T){
	if(T==NULL){return ;}
	cout<<T->data<<" ";
	PreTravel(T->Lchild);
	PreTravel(T->Rchild);
}
BiTree* PastFindAncient(BiTree* T){
	BiTree* left=NULL;BiTree* right=NULL;
	if(T->Lchild==NULL&&T->Rchild==NULL||T->data==val1||T->data==val2){
		if(T->data==val1||T->data==val2){
			return T;
		}
		else{
			return NULL;
		}
	}
	if(T->Lchild){
		left=PastFindAncient(T->Lchild);
	}
	if(T->Rchild){
		right=PastFindAncient(T->Rchild);
	}
	if(left!=NULL&&right!=NULL){//此时说明找到了 
		cout<<"此时找到了结点"<<T->data<<"便是公共祖先"<<endl; 
		return T; 
	}
	else if(left){
		return left;
	}
	else if(right){ 
		return right;
	}
	else{ 
		return NULL;
	}
}
BiTree* RePastFindAncient(BiTree* T){
	stack<BiTree*> S;
	stack<BiTree*> S1,S2,S3,S4;
	if(T==NULL)  return NULL;
	S.push(T);
	while(!S.empty()){
		T=S.top();
		if(T==NULL){
			S.pop(); 
			T=S.top();
			if(T->data==val1){//此时栈中后面跟一个NULL便是祖先 
				while(!S.empty()){
					BiTree* cur=S.top();
					S.pop();
					result1.push_back(cur); 
					S2.push(cur); 
				}//将S中中元素倒入S1,S2中
				while(!S2.empty()){//再将S2中元素倒回 
					BiTree* cur=S2.top();
					S2.pop();
					S.push(cur);; 
				} 
			}
			if(T->data==val2){//此时栈中都是后发现元素的祖先,与上相同操作 
				while(!S.empty()){
					BiTree* cur=S.top();
					S.pop();
					result2.push_back(cur);
					S4.push(cur); 
				}//将S中中元素倒入S3,S4中
				while(!S4.empty()){//再将S2中元素倒回 
					BiTree* cur=S4.top();
					S4.pop();
					S.push(cur);; 
				} 				
			} 
			S.pop();
		} 
		else{
			S.pop();
			S.push(T);
			S.push(NULL); 
			if(T->Rchild)S.push(T->Rchild);
			if(T->Lchild)S.push(T->Lchild);	
		}
	} 
	BiTree* cur=NULL;
	reverse(result1.begin(),result1.end());
	reverse(result2.begin(),result2.end());
	cout<<"向量一是"<<endl;
	for(int i=0;i<result1.size();i++){
		if(result1[i]!=NULL){
			cout<<result1[i]->data<<" ";
		}
		else{
			cout<<"NULL"<<" ";
		}
	}cout<<endl; 
	cout<<"向量二是"<<endl;
	for(int i=0;i<result2.size();i++){
		if(result2[i]!=NULL){
			cout<<result2[i]->data<<" ";
		}
		else{
			cout<<"NULL"<<" "; 
		}
	}cout<<endl;
	for(int i=0;i<result1.size()&&i<result2.size();i++){
		if(result2.size()<result1.size()){
			if(result1[i]==result2[i]&&result1[i]!=NULL&&result1[i+1]==NULL){
			cur=result1[i];}
		}
		else{
			if(result1[i]==result2[i]&&result1[i]!=NULL&&result2[i+1]==NULL){
			cur=result1[i];}
		}
	}
	return cur;
}
int main(){
	BiTree* T;
	cout<<"请输入结点,其中空结点使用-1 代替"<<endl;
	PreCreatTree(T);
	PreTravel(T);cout<<endl; 
	while(1){
		result1.clear();result2.clear();
		//S1.clear();S2.clear();S3.clear();S4.clear();
		cout<<"请输入你要查找的值"<<endl;
		cin>>val1;cin>>val2;
		if(PastFindAncient(T)==NULL){
			cout<<"此时未找到"<<endl; 
		} 
		else{
			cout<<"递归此找到公共结点"<<PastFindAncient(T)->data<<endl; 
		}
	/**************下为迭代法**************************/ 
		BiTree* cur=RePastFindAncient(T);
		if(cur==NULL){
			cout<<"迭代此时未找到"<<endl; 
		} 
		else{
			cout<<"迭代此找到公共结点"<<cur->data<<endl; 
		}	
	}
	
}

csdn文章推荐受影响解决办法10个字10行
csdn文章推荐受影响解决办法10个字10行
csdn文章推荐受影响解决办法10个字10行
csdn文章推荐受影响解决办法10个字10行
csdn文章推荐受影响解决办法10个字10行
csdn文章推荐受影响解决办法10个字10行
csdn文章推荐受影响解决办法10个字10行
csdn文章推荐受影响解决办法10个字10行
csdn文章推荐受影响解决办法10个字10行
csdn文章推荐受影响解决办法10个字10行

你可能感兴趣的:(#,树相关题目,算法,数据结构,c++)