出处:https://segmentfault.com/a/1190000003509399
二叉搜索树:
Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that
has both v and w as descendants (where we allow a node to be a descendant of itself).”
_______6______
/ \
___2__ ___8__
/ \ / \
0 _4 7 9
/ \
3 5
For example, the lowest common ancestor (LCA) of nodes 2 and 8 is 6.
Another example is LCA of nodes 2 and 4 is 2,
since a node can be a descendant of itself according to the LCA definition.
思路:
对于二叉搜索树来说,公共祖先的值一定大于等于较小的节点,小于等于较大的节点。换言之,在遍历树的时候,如果当前结点大于两个节点,则结果在当前结点的左子树里,如果当前结点小于两个节点,则结果在当前节点的右子树里。
代码如下:
//二叉搜索树两个节点的最低公共祖先,参数为两个节点的值
BinaryTreeNode*lowestCommonAncestorOfBST(BinaryTreeNode*pNode, int nNodeOne, int nNodeTwo){
if (pNode==NULL)
{
return NULL;
}
if (pNode->m_nValue>nNodeOne && pNode->m_nValue>nNodeTwo)//当前节点的值大于这两个节点的值
{
return lowestCommonAncestorOfBST(pNode->m_pLeft, nNodeOne, nNodeTwo);//访问左子树
}
if (pNode->m_nValuem_nValuem_pRight, nNodeOne, nNodeTwo);//访问右子树
}
return pNode;//就是公共祖先
}
//二叉搜索树两个节点的最低公共祖先,参数为两个节点
BinaryTreeNode*lowestCommonAncestorOfBST(BinaryTreeNode*pNode, BinaryTreeNode*pNode1, BinaryTreeNode*pNode2){
if (pNode==NULL)
{
return NULL;
}
if (pNode->m_nValue>pNode1->m_nValue && pNode->m_nValue>pNode2->m_nValue)//当前节点的值大于这两个节点的值
{
return lowestCommonAncestor(pNode->m_pLeft, pNode1, pNode2);//访问左子树
}
if (pNode->m_nValuem_nValue && pNode->m_nValuem_nValue)//当前节点的值小于这两个节点的值
{
return lowestCommonAncestor(pNode->m_pRight, pNode1, pNode2);//访问右子树
}
return pNode;//就是公共祖先
}
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”
_______3______
/ \
___5__ ___1__
/ \ / \
6 _2 0 8
/ \
7 4
For example, the lowest common ancestor (LCA) of nodes 5 and 1 is 3. Another example is LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.
思路:
我们可以用深度优先搜索,从叶子节点向上,标记子树中出现目标节点的情况。如果子树中有目标节点,标记为那个目标节点,如果没有,标记为null。显然,如果左子树、右子树都有标记,说明就已经找到最小公共祖先了。如果在根节点为p的左右子树中找p、q的公共祖先,则必定是p本身。
换个角度,可以这么想:如果一个节点左子树有两个目标节点中的一个,右子树没有,那这个节点肯定不是最小公共祖先。如果一个节点右子树有两个目标节点中的一个,左子树没有,那这个节点肯定也不是最小公共祖先。只有一个节点正好左子树有,右子树也有的时候,才是最小公共祖先。
代码如下:
//两个节点的最低公共祖先,参数为两个节点
BinaryTreeNode* lowestCommonAncestor(BinaryTreeNode*pNode, BinaryTreeNode*pNode1, BinaryTreeNode*pNode2){
//发现目标节点则通过返回值标记该子树发现了某个目标结点
if (pNode == NULL || pNode == pNode1 || pNode == pNode2) return pNode;
//查看左子树中是否有目标结点,没有为null
BinaryTreeNode*left = lowestCommonAncestor(pNode->m_pLeft, pNode1, pNode2);
//查看右子树是否有目标节点,没有为null
BinaryTreeNode*right = lowestCommonAncestor(pNode->m_pRight, pNode1, pNode2);
//都不为空,说明做右子树都有目标结点,则公共祖先就是本身
if (left != NULL&&right != NULL) return pNode;
//如果发现了目标节点,则继续向上标记为该目标节点
return left == NULL ? right : left;
}
//两个节点的最低公共祖先,参数为两个节点的值
BinaryTreeNode* lowestCommonAncestor(BinaryTreeNode*pNode, int nNodeOne, int nNodeTwo){
//发现目标节点则通过返回值标记该子树发现了某个目标结点
if (pNode == NULL || pNode->m_nValue == nNodeOne || pNode->m_nValue == nNodeTwo) return pNode;
//查看左子树中是否有目标结点,没有为null
BinaryTreeNode*left = lowestCommonAncestor(pNode->m_pLeft, nNodeOne, nNodeTwo);
//查看右子树是否有目标节点,没有为null
BinaryTreeNode*right = lowestCommonAncestor(pNode->m_pRight, nNodeOne, nNodeTwo);
//都不为空,说明做右子树都有目标结点,则公共祖先就是本身
if (left != NULL&&right != NULL) return pNode;
//如果发现了目标节点,则继续向上标记为该目标节点
return left == NULL ? right : left;
}
二叉搜索树 普通的二叉树
下面是测试代码:
//先序创建二叉树
void CreatBTree(BinaryTreeNode *&root)
{
int nValue = 0;
cin >> nValue;
if (-1 == nValue)//-1代表为空
{
return;
}
else
{
root = new BinaryTreeNode();
root->m_nValue = nValue;
CreatBTree(root->m_pLeft);
CreatBTree(root->m_pRight);
}
}
int main(){
BinaryTreeNode*T = NULL;
BinaryTreeNode*pTreeOfBST = NULL;
cout << "先序构建二叉树:" << endl;
CreatBTree(T);
cout << "先序构建二叉搜索树:" << endl;
CreatBTree(pTreeOfBST);
int nNodeOne, nNodeTwo;
while (true)
{
cout << endl;
cout <<"输入二叉搜索树两个节点:"<< endl;
cin >> nNodeOne >> nNodeTwo;
BinaryTreeNode*common = lowestCommonAncestorOfBST(pTreeOfBST, nNodeOne, nNodeTwo);
cout << "二叉搜索树中两个节点的最低公共祖先为:" << endl;
cout << common->m_nValue << endl;
cout << "输入普通树两个节点:" << endl;
cin >> nNodeOne >> nNodeTwo;
common = lowestCommonAncestor(T, nNodeOne, nNodeTwo);
cout << "普通树中两个节点的最低公共祖先为:" << endl;
cout << common->m_nValue << endl;
}
return 0;
}