求二叉树中两个节点的最近公共祖先结点
二叉树是搜索二叉树 1、原理:二叉搜索树是排序过的 ,位于左子树的结点都比父结点小,位于右子树的结点都比父结点大,我们只需从根节点开始和两个输入的结点进行比较,如果当前节点的值比两个结点的值都大,那么最低的公共祖先结点一定在该结点的左子树中,下一步开遍历当前结点的左子树。如果当前节点的值比两个结点的值都小,那么最低的公共祖先结点一定在该结点的右子树中,下一步开遍历当前结点的右子树。这样从上到下找到第一个在两个输入结点的值之间的结点。
【求二叉树中两个节点的最近公共祖先结点】2、实现代码
BinaryNode* CreateBinaryTree(int* array, int length)
{
BinaryNode* root = new BinaryNode(array[0]);
BinaryNode* pTemp = NULL;
for (int idx = 1;
idx < length;
idx++)
{
BinaryNode* pCur = root;
//寻找插入位置
while (pCur)
{
if (array[idx]_value)
{
pTemp = pCur;
pCur = pCur->_left;
}
else if (array[idx]>pCur->_value)
{
pTemp = pCur;
pCur = pCur->_right;
}
else
return NULL;
}
//插入元素
pCur = new BinaryNode(array[idx]);
if (array[idx] < pTemp->_value)
pTemp->_left = pCur;
else
pTemp->_right = pCur;
}
return root;
}//搜素二叉树寻找最近公共祖先节点
BinaryNode* AncestorTreeNode(BinaryNode* pRoot, BinaryNode* node1, BinaryNode* node2)
{
if (pRoot == NULL)
return NULL;
if (node1 == NULL)
return node2;
if (node2 == NULL)
return node1;
while (pRoot)
{
if (pRoot->_value > node1->_value && pRoot->_value > node2->_value)
pRoot = pRoot->_left;
if (pRoot->_value < node1->_value && pRoot->_value < node2->_value)
pRoot = pRoot->_right;
else
return pRoot;
}
return NULL;
}
测试用例:
void FunTest1()
{
BinaryNode* pRoot = NULL;
int array[] = { 5, 2, 6 };
int length = sizeof(array) / sizeof(array[0]);
pRoot = CreateBinaryTree(array, length);
BinaryNode* node1 = pRoot->_left->_left;
BinaryNode* node2 = pRoot->_left->_right;
BinaryNode* pNode = AncestorTreeNode(pRoot, node1, node2);
if (pNode)
cout << pNode->_value << endl;
}
二叉树节点中包含指向父节点的指针 1、原理:如果树中每个结点都有父结点(根结点除外),这个问题可以转换成求两个链表的第一个公共结点,假设树结点中指向父结点的指针是parent,树的每一个叶结点开始都由一个指针parent串起来的链表,每个链表的尾结点就是树的根结点。那么输入的这两个结点位于链表上,它们的最低公共祖先结点刚好是这两个链表的第一个公共结点。 2、实现代码
int Hight(BinaryNode* root, BinaryNode* node)
{
int len = 0;
while (node)
{
len++;
node = node->_parent;
}
return len;
}
BinaryNode* GetLastCommonAncestor(BinaryNode* root, BinaryNode* node1, BinaryNode* node2)
{ if (root == NULL || node1 == NULL || node2 == NULL)
return NULL;
int len1 = Hight(root, node1);
//一个链表的高度
int len2 = Hight(root, node2);
//另一个链表的高度
//寻找两个链表的第一个交点
while (len1 != len2)
{
if (len1 < len2)
len2--;
else
len1--;
} while (node1 && node2 && node1 != node2)
{
node1 = node1->_parent;
node2 = node2->_parent;
} if (node1 == node2)
return node1;
else
return NULL;
}
测试用例
void FunTest()
{
BinaryNode* root = new BinaryNode(1);
BinaryNode* cur = root;
queue q;
BinaryNode* top = NULL;
q.push(root);
for (int i = 2;
i <= 7;
i++)
{
if (!q.empty())
{
top = q.front();
if (cur == top->_left)
{
cur = new BinaryNode(i);
top->_right = cur;
cur->_parent = top;
q.pop();
}
else
{
cur = new BinaryNode(i);
top->_left = cur;
cur->_parent = top;
}
q.push(cur);
}
}
BinaryNode* node1 = root->_left->_left;
BinaryNode* node2 = root->_left->_right;
BinaryNode* ancestor = GetLastCommonAncestor(root, node1, node2);
if (ancestor)
cout << ancestor->_value << endl;
else
cout << "没有公共祖先" << endl;
}
二叉树是普通二叉树, 没有指向父结点的指针 1、原理:在二叉树根结点 的左子树和右子树中分别找输入的两个结点,如果两个结点都在左子树,遍历当前结点的左子树,如果两个结点都在右子树,遍历当前结点的右子树,直到一个在当前结点的左子树,一个在当前结点的右子树,返回当前结点就是最低的公共祖先结点。 2、实现代码
bool IsNodeInTree(BinaryNode* pRoot, BinaryNode* pNode)
{
if (pRoot == NULL || pNode == NULL)
return false;
if (pNode == pRoot)
return true;
if (IsNodeInTree(pRoot->_left, pNode) || IsNodeInTree(pRoot->_right, pNode))
return true;
return false;
}
BinaryNode* GetCommonAncestor(BinaryNode* pRoot, BinaryNode* node1, BinaryNode* node2)
{
if (pRoot == NULL)
return NULL;
if (node1 == pRoot && IsNodeInTree(pRoot, node2) || node2 == pRoot && IsNodeInTree(pRoot, node1))
return pRoot;
bool node1left = IsNodeInTree(pRoot->_left, node1);
bool node1right = IsNodeInTree(pRoot->_right, node1);
bool node2left = IsNodeInTree(pRoot->_left, node2);
bool node2right = IsNodeInTree(pRoot->_right, node2);
if (node1left && node2right || node1right && node2left)
return pRoot;
if (node1left && node2left)
return GetCommonAncestor(pRoot->_left, node1, node2);
if (node1right && node2right)
return GetCommonAncestor(pRoot->_right, node1, node2);
return NULL;
}
测试用例
void FunTest3()
{
BinaryNode* root = new BinaryNode(1);
BinaryNode* cur = root;
queue q;
BinaryNode* top = NULL;
q.push(root);
for (int i = 2;
i <= 7;
i++)
{
if (!q.empty())
{
top = q.front();
if (cur == top->_left)
{
cur = new BinaryNode(i);
top->_right = cur;
cur->_parent = top;
q.pop();
}
else
{
cur = new BinaryNode(i);
top->_left = cur;
cur->_parent = top;
}
q.push(cur);
}
}
BinaryNode* node1 = root->_left->_left;
BinaryNode* node2 = root->_left->_right;
BinaryNode* ancestor = GetCommonAncestor(root, node1, node2);
if (ancestor)
cout << ancestor->_value << endl;
else
cout << "没有公共祖先" << endl;
}
头文件和结点的结构体
#include
#include
using namespace std;
struct BinaryNode
{
BinaryNode* _left;
BinaryNode* _right;
BinaryNode* _parent;
int _value;
BinaryNode(const int& value)
:_value(value)
, _left(NULL)
, _right(NULL)
, _parent(NULL)
{}
};
推荐阅读
- 有句话忍很久了,女生要求买房怎么就物质了()
- java中如何实现重建二叉树
- 基于爱,才会有“愿望”当“要求”。2017.8.12
- 先放下|先放下 ,求一个好心情
- https请求被提早撤回
- 遇到不正当请求怎么办
- 二叉树路径节点关键值和等于目标值(LeetCode--112&LeetCode--113)
- 保姆有偿陪伴(雇主要求过分,保姆没自尊,53岁保姆果断离职)
- 【求助】03
- 发火其实是在求救