祖先节点
祖先节点指从根开始到该节点路径上的所有节点
思路
拿到这道题先分析树是什么树,是搜索树还是普通的二叉树。
搜索树
由搜索树性质可得,如果根的左子树所有节点比根小,根的右子树所有节点比根大。
那么分一下几种情况:
1 某一个节点为根节点,那么公共节点就是根节点了。
2 这俩个节点在不同子树,那么公共节点就是根节点。
3 这俩个节点在同一子树。
所以根据以上分析,可得我们可以通过不断的递归直到找到一个子树,在该子树中俩节点分别位于它的左子树和右子树,那么该子树节点就是公共节点。
代码
Node* findCom_ancestor(Node*Root, Node*x, Node*x2)
{
if (Root == NULL) return NULL;
if (x == Root || x2 == Root) return Root;
if (x->_data > Root->_data&&x2->_data < Root->_data)
{
return Root;
}
if (x->_data<Root->_data&&x2->_data>Root->_data)
{
return Root;
}
if (x->_data < Root->_data)
{
return findCom_ancestor(Root->_PLeft, x, x2);
}
else{
return findCom_ancestor(Root->_PRight, x, x2);
}
}
普通二叉树
思路
方法1
以上面的思路为参考,只要不断的判断俩节点是否位于不同子树即可,找到位于不同子树的根节点即可。
所以每次都要判断一次是否在该子树中。所以时间复杂度较高为 N2。
方法2
自己写个关于路径的函数,保存路径上的所有节点到栈中,通过栈的特性后进先出,所以从该节点从上一直遍历栈中保存的节点信息,是否有相同的,第一个相同的即为最近公共祖先节点。
方法2代码
bool path(stack<Node*>& s, Node*Root, Node*x)
{
if (Root)
{
if (Root == x)
{
return true; //这里找到不用在push了,因为是先入栈再查找的
}
s.push(Root->_PLeft); //先入栈假设在左子树
if (path(s, Root->_PLeft, x)) //进左子树查找
return true;
else
s.pop(); //走到这里这里说明左子树没有,所以把之前入栈的左子树节点pop出来
s.push(Root->_PRight); //再继续假设在右子树
if (path(s, Root->_PRight, x)) //查找
return true;
else
s.pop(); //不在右子树把之前的节点出栈
}
return false;
}
Node* findCom_ancestor(Node*Root, Node*x, Node*x2)
{
if (Root == NULL || x == NULL || x2 == NULL)
{
return NULL;
}
if (Root==x||Root==x2)
{
return Root;
}
/*path处理,先保存路径所有节点*/
stack<Node*> scon1;
stack<Node*> scon2;
scon1.push(Root);//这里我先把Root入栈是因为我写的Path函数里没有把Root入栈,只是把路径上的所有子节点放入栈中
scon2.push(Root);
if (!path(scon1, Root, x)) return NULL; //如果没找到,说明该节点不在此子树中所以return NULL
if (!path(scon2, Root, x2)) return NULL;
int gap = 0;//走到这 scon肯定不为空
int size = scon1.size();
int size2 = scon2.size();
gap = (size > size2) ? size - size2 : size2 - size;
if (size > size2)
{
while (gap-- != 0)
{
scon1.pop();
}
}
if (size2 > size)
{
while (gap-- != 0)
{
scon2.pop();
}
}
/*这里处理栈中数据看找到最近祖先节点*/
Node*pCur = scon1.top();
Node*pCur_2 = scon2.top();
while (pCur != pCur_2) //先比较再pop
{
scon1.pop();
scon2.pop();
if (scon1.empty()||scon2.empty()) break;
pCur = scon1.top(); //即使这里俩个都取到最后一个节点也没问题,因为是先比较的
pCur_2 = scon2.top();
}
if (pCur == pCur_2) return pCur;
return NULL;
}