C++实现寻找最低公共父节点的方法

所属分类: 软件编程 / C 语言 阅读数: 81
收藏 0 赞 0 分享

本文实例讲述了C++实现寻找最低公共父节点的方法,是数据结构中二叉树的经典算法。分享给大家供大家参考。具体方法如下:

最低公共父节点,意思很好理解。

思路1:最低公共父节点满足这样的条件:两个节点分别位于其左子树和右子树,那么定义两个bool变量,leftFlag和rightFlag,如果在左子树中,leftFlag为true,如果在右子树中,rightFlag为true,仅当leftFlag == rightFlag == true时,才能满足条件。

实现代码如下:

#include <iostream>

using namespace std;

struct Node
{
 Node(int i = 0, Node *pLeft = NULL, Node *pRight = NULL) : data(i), left(pLeft),
 right(pRight) {}
 Node *left;
 Node *right;
 int data;
};

Node *constructNode(Node **pNode1, Node **pNode2)
{
 Node *node12 = new Node(12);
 Node *node11 = new Node(11);
 Node *node10 = new Node(10);
 Node *node9 = new Node(9, NULL, node12);
 Node *node8 = new Node(8, node11, NULL);
 Node *node7 = new Node(7);
 Node *node6 = new Node(6);
 Node *node5 = new Node(5, node8, node9);
 Node *node4 = new Node(4, node10);
 Node *node3 = new Node(3, node6, node7);
 Node *node2 = new Node(2, node4, node5);
 Node *node1 = new Node(1, node2, node3);

 *pNode1 = node6;
 *pNode2 = node12;

 return node1;
}

bool isNodeIn(Node *root, Node *node1, Node *node2)
{
 if (node1 == NULL || node2 == NULL)
 {
 throw("invalid node1 and node2");
 return false;
 }
 if (root == NULL)
 return false;

 if (root == node1 || root == node2)
 {
 return true;
 }
 else
 {
 return isNodeIn(root->left, node1, node2) || isNodeIn(root->right, node1, node2);
 }
}

Node *lowestFarther(Node *root, Node *node1, Node *node2)
{
 if (root == NULL || node1 == NULL || node2 == NULL || node1 == node2)
 {
 return NULL;
 }
 
 bool leftFlag = false;
 bool rightFlag = false;
 leftFlag = isNodeIn(root->left, node1, node2);
 rightFlag = isNodeIn(root->right, node1, node2);

 if (leftFlag == true && rightFlag == true)
 {
 return root;
 }
 else if (leftFlag == true)
 {
 return lowestFarther(root->left, node1, node2);
 }
 else
 {
 return lowestFarther(root->right, node1, node2);
 }
}

void main()
{
 Node *node1 = NULL;
 Node *node2 = NULL;
 Node *root = constructNode(&node1, &node2);

 cout << "node1: " << node1->data << endl;
 cout << "node2: " << node2->data << endl;
 cout << "root: " << root->data << endl;

 Node *father = lowestFarther(root, node1, node2);

 if (father == NULL)
 {
 cout << "no common father" << endl;
 }
 else
 {
 cout << "father: " << father->data << endl;
 }
}

这类问题在面试的时候常会遇到,对此需要考虑以下情形:

1. node1和node2指向同一节点,这个如何处理
2. node1或node2有不为叶子节点的可能性吗
3. node1或node2一定在树中吗

还要考虑一个效率问题,上述代码中用了两个递归函数,而且存在不必要的递归过程,仔细思考,其实一个递归过程足以解决此问题

实现代码如下:

#include <iostream>

using namespace std;

struct Node
{
 Node(int i = 0, Node *pLeft = NULL, Node *pRight = NULL) : data(i),
 left(pLeft), right(pRight) {}
 int data;
 Node *left;
 Node *right;
};

Node *constructNode(Node **pNode1, Node **pNode2) 
{ 
 Node *node12 = new Node(12); 
 Node *node11 = new Node(11); 
 Node *node10 = new Node(10); 
 Node *node9 = new Node(9, NULL, node12); 
 Node *node8 = new Node(8, node11, NULL); 
 Node *node7 = new Node(7); 
 Node *node6 = new Node(6); 
 Node *node5 = new Node(5, node8, node9); 
 Node *node4 = new Node(4, node10); 
 Node *node3 = new Node(3, node6, node7); 
 Node *node2 = new Node(2, node4, node5); 
 Node *node1 = new Node(1, node2, node3); 

 *pNode1 = node6; 
 *pNode2 = node5; 

 return node1; 
}

bool lowestFather(Node *root, Node *node1, Node *node2, Node *&dest)
{
 if (root == NULL || node1 == NULL || node2 == NULL || node1 == node2)
 return false;
 if (root == node1 || root == node2)
 return true;

 bool leftFlag = lowestFather(root->left, node1, node2, dest);
 bool rightFlag = lowestFather(root->right, node1, node2, dest);
 
 if (leftFlag == true && rightFlag == true)
 {
 dest = root;
 }
 if (leftFlag == true || rightFlag == true)
 return true;
}

int main()
{
 Node *node1 = NULL;
 Node *node2 = NULL;
 Node *root = constructNode(&node1, &node2);

 bool flag1 = false;
 bool flag2 = false;
 Node *dest = NULL;
 bool flag = lowestFather(root, node1, node2, dest);

 if (dest != NULL)
 {
 cout << "lowest common father: " << dest->data << endl;
 }
 else
 {
 cout << "no common father!" << endl;
 }

 return 0;
}

下面再换一种方式的写法如下:

#include <iostream>

using namespace std;

struct Node
{
 Node(int i = 0, Node *pLeft = NULL, Node *pRight = NULL) : data(i),
 left(pLeft), right(pRight) {}
 int data;
 Node *left;
 Node *right;
};

Node *constructNode(Node **pNode1, Node **pNode2) 
{ 
 Node *node12 = new Node(12); 
 Node *node11 = new Node(11); 
 Node *node10 = new Node(10); 
 Node *node9 = new Node(9, NULL, node12); 
 Node *node8 = new Node(8, node11, NULL); 
 Node *node7 = new Node(7); 
 Node *node6 = new Node(6); 
 Node *node5 = new Node(5, node8, node9); 
 Node *node4 = new Node(4, node10); 
 Node *node3 = new Node(3, node6, node7); 
 Node *node2 = new Node(2, node4, node5); 
 Node *node1 = new Node(1, node2, node3); 

 *pNode1 = node11; 
 *pNode2 = node12; 

 return node1; 
}

Node* lowestFather(Node *root, Node *node1, Node *node2)
{
 if (root == NULL || node1 == NULL || node2 == NULL || node1 == node2)
 return NULL;
 if (root == node1 || root == node2)
 return root;

 Node* leftFlag = lowestFather(root->left, node1, node2);
 Node* rightFlag = lowestFather(root->right, node1, node2);

 if (leftFlag == NULL)
 return rightFlag;
 else if (rightFlag == NULL)
 return leftFlag;
 else
 return root;
}

int main()
{
 Node *node1 = NULL;
 Node *node2 = NULL;
 Node *root = constructNode(&node1, &node2);

 bool flag1 = false;
 bool flag2 = false;
 Node *dest = NULL;
 Node* flag = lowestFather(root, node1, node2);

 if (flag != NULL)
 {
 cout << "lowest common father: " << flag->data << endl;
 }
 else
 {
 cout << "no common father!" << endl;
 }

 return 0;
}

希望本文所述对大家C++程序算法设计的学习有所帮助。

更多精彩内容其他人还在看

C++中四种对象生存期和作用域以及static的用法总结分析

以下是对C++中四种对象生存期和作用域以及static的用法进行了详细的介绍,需要的朋友可以过来参考下
收藏 0 赞 0 分享

C++嵌套类与局部类详细解析

从作用域的角度看,嵌套类被隐藏在外围类之中,该类名只能在外围类中使用。如果在外围类之外的作用域使用该类名时,需要加名字限定
收藏 0 赞 0 分享

C++空类详解

以下是对C++中的空类进行了详细的介绍,需要的朋友可以过来参考下
收藏 0 赞 0 分享

C++之友元:友元函数和友元类详解

友元是一种允许非类成员函数访问类的非公有成员的一种机制。可以把一个函数指定为类的友元,也可以把整个类指定为另一个类的友元
收藏 0 赞 0 分享

C++中返回指向函数的指针示例

int (*ff(int)) (int *,int);表示:ff(int)是一个函数,带有一个int型的形参,该函数返回int (*) (int *,int),它是一个指向函数的指针,所指向的函数返回int型并带有两个分别是Int*和int型的形参
收藏 0 赞 0 分享

C数据结构之单链表详细示例分析

以下是对C语言中的单链表进行了详细的分析介绍,需要的朋友可以过来参考下
收藏 0 赞 0 分享

C数据结构之双链表详细示例分析

以下是对c语言中的双链表进行了详细的分析介绍,需要的朋友可以过来参考下
收藏 0 赞 0 分享

浅析如何在c语言中调用Linux脚本

如何在c语言中调用Linux脚本呢?下面小编就为大家详细的介绍一下吧!需要的朋友可以过来参考下
收藏 0 赞 0 分享

深入解析unsigned int 和 int

以下是对unsigned int和int进行了详细的分析介绍,需要的朋友可以过来参考下
收藏 0 赞 0 分享

浅谈C++中的string 类型占几个字节

本篇文章小编并不是为大家讲解string类型的用法,而是讲解我个人比较好奇的问题,就是string 类型占几个字节
收藏 0 赞 0 分享
查看更多