给定二叉树(不是二叉搜索树)和两个节点n1和n2,编写程序以找到他们的最近公共祖先(Lowest Common Ancestor, LCA )。
LCA定义
最近公共祖先是两个节点所有公共祖先中离根节点最远的节点。
计算节点的最近公共祖先是很有用的。
例如,为了确定树中节点之间距离:从n1节点到n2节点的距离,可以计算从根到n1的距离加上从根到n2的距离,减去从根到它们最近共同祖先的距离的两倍。
方法
我们可以从根开始遍历树。 如果任一给节点(n1和n2)与根匹配,则根为LCA。
如果根与任何节点都不匹配,我们重复左右子树中寻找节点n1和n2。
如果在其左子树中存在一个节点而在右子树中存在的另一个节点,则此节点即为LCA。
如果两个节点都位于左子树中,则LCA也位于左子树中,
否则LCA位于右子树中。
#include <iostream> using namespace std; // 二叉树节点 struct Node { struct Node *left, *right; int key; }; // 根据给定的值,创建一个二叉树节点,其左右子树均为空 Node* newNode(int key) { Node *temp = new Node; temp->key = key; temp->left = temp->right = NULL; return temp; } // 返回指向给定节点 n1 和 n1 LCA 的指针 // 此方法假定节点 n1 和 n2 在数中均出现 struct Node *findLCA(struct Node* root, int n1, int n2) { if (root == NULL) return NULL; // 如果任一给节点(n1和n2)与根匹配,则根为LCA if (root->key == n1 || root->key == n2) return root; // 在左右子树中找给定节点 Node *left_lca = findLCA(root->left, n1, n2); Node *right_lca = findLCA(root->right, n1, n2); // 左子树存在一个给定节点
// 右子树存在另一给定节点
// 则根为 LCA if (left_lca && right_lca) return root; // 否则 LCA 位于左子树或者右子树 return (left_lca != NULL)? left_lca: right_lca; } int main() { Node * root = newNode(1); root->left = newNode(2); root->right = newNode(3); root->left->left = newNode(4); root->left->right = newNode(5); root->right->left = newNode(6); root->right->right = newNode(7); cout << "LCA(4, 5) = " << findLCA(root, 4, 5)->key; cout << "nLCA(4, 6) = " << findLCA(root, 4, 6)->key; cout << "nLCA(3, 4) = " << findLCA(root, 3, 4)->key; cout << "nLCA(2, 4) = " << findLCA(root, 2, 4)->key; return 0; }