給定二叉樹(不是二叉搜索樹)和兩個節點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; }