树(二叉链表,非递归)两结点的最近公共祖先结点

/*
二叉链表非递归 查找两个结点的最近公共结点

思路:
把一个结点的全部父结点都放到栈中(类似于查找从根结点到某一结点的路径)
依次出栈判断这棵树的后代中是否包括另一个结点
*/
#include <iostream> 
#include <cstdlib>
using namespace std;

const int maxsize = 100;

typedef struct BiTNode{
	char data;
	struct BiTNode *lchild, *rchild;
}*BiTree;
void createTree(BiTree &T){
	char c;
	cin >> c;
	if(c == '#')
		T = NULL;
	else{
		T = (BiTree)malloc(sizeof(BiTNode));
		T->data = c;
		createTree(T->lchild);
		createTree(T->rchild);
	}
}

//将结点c的全部祖先结点依次入栈
BiTree stack[maxsize];
int top = -1;
void getNode(BiTree T, char c){
	BiTree p;
	int tag[maxsize];	//0表示该结点未被扫描过 
	p = T;
	do{
		//靠左的结点全部入栈
		while(p){
			stack[++top] = p;	//结点入栈 
			tag[top] = 0;			
			p = p->lchild;
		}
		//栈非空 
		if(top>=0){	
			//结点已经访问过
			if(tag[top] == 1){
				if(stack[top]->data == c){
					break;	//结点不重复就退出,结点有重复就继续 
				}
				top--;
			} 
			//结点未访问过
			else{
				p = stack[top];
				p = p->rchild;	//扫描右结点
				tag[top] = 1;	//该结点已被扫描过
			} 
		}
	}while(top>=0 || p);		//栈非空 或者 p结点不为空--继续循环 
} 
//判断树T的后代结点中是否有结点c(不能用遍历算法的递归形式,那样没办法判断没有所要查找结点的情况)
bool preSearch(BiTree T, char c){
	BiTree p, s[maxsize];
	int top;
	if(T){
		top = 1;
		s[top] = T;
		while(top>0){	//栈不空 
			p = s[top--];		//退栈并访问该结点 
			
			//这里要注意判断孩子结点是否是要找的结点的前提必须保证p的左右结点非空
			if(p->rchild) {
				s[++top] = p->rchild;	//右孩子进栈 
				if(s[top]->data == c)	
					return true;
			}
			if(p->rchild) {
				s[++top] = p->lchild;	//左孩子进栈 
				if(s[top]->data == c)	
					return true;
			}
		}
	}
	return false;
}
//找结点v和结点c的最近公共祖先结点
BiTree findFirstCommonParentNode(BiTree T, char c, char v){
	//把结点c的全部父结点入栈
	getNode(T, c);
	
	//栈不空
	while(top>-1){	
		BiTree t = stack[top--];
		
		//判断树t的后代结点中是否包括结点v
		if(preSearch(t, v))
			return t;
	}
	return NULL;
}
int main(){
	BiTree T, p;
	char c, v;
	T = (BiTree)malloc(sizeof(BiTNode));
	
	cout << "输入树的结点:";
	createTree(T);
	cout << "输入带判断的结点:"; 
	cin >> c >> v;
	
	p = findFirstCommonParentNode(T, c, v) ;
	cout << "公共结点:" << p->data << endl;
	return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值