[英]Find the lowest common ancestor of two nodes from adjacency list
如果我知道樹中存在的每個節點的鄰接列表,那么我如何找出該樹中存在的任何兩個節點的最低共同祖先?
實際上,我想找出任意兩個節點之間的距離,因此我想計算LCA。 有什么方法可以從鄰接表中計算出來嗎?
T中的n1和n2的LCA是距離根最遠的n1和n2的共享祖先。 最低共同祖先的計算可能有用,例如,作為確定樹中節點對之間距離的過程的一部分:從n1到n2的距離可以計算為從根到n1的距離加上距離從根到n2,減去從根到其最低共同祖先的距離的兩倍。 ( 來源維基 )
我們正在處理鄰接表的事實並不能真正解決問題。
查找節點A和B的LCA的基本思路如下:
無論哪種情況,都可以通過返回指示符將上述檢查相當容易地合並到單個函數中。
在無序樹中,必須在最壞的情況下瀏覽整個樹,但是在二叉搜索樹中,只需將其值與當前節點進行比較,就可以輕松地檢查左或右子樹是否可以包含一個節點。
但實際上您不應該使用LCA算法來確定距離。 您應該修改以上內容以返回距離而不是LCA。 對此的修改相當簡單:
您可以嘗試以下方法:
class Node
{
public:
// Other stuff.
const Node* getParent() const { return parent; }
private:
Node* parent;
std::vector<Node*> children;
};
const Node* getLowestCommonAncestor(const Node& lhs, const Node& rhs)
{
for (const Node* node1 = &lhs; node1 != nullptr; node1 = node1->getParent()) {
for (const Node* node2 = &rhs; node2 != nullptr; node2 = node2->getParent()) {
if (node1 == node2) {
return node1;
}
}
}
return nullptr;
}
或者,如果您沒有父母:
namespace detail
{
struct LCAFlag {
enum { NoFound = 0, leftFound = 1, rightFound = 2 };
};
const Node* getLCA_Rec(const Node& root, const Node& lhs, const Node& rhs, unsigned int& flag)
{
if (&root == &lhs) {
flag |= LCAFlag::leftFound;
} else if (&root == &rhs) {
flag |= LCAFlag::rightFound;
}
if (flag == (LCAFlag::leftFound | LCAFlag::rightFound)) {
return nullptr; // both found. parent is the LCA
}
for (auto it = root.children.begin(); it != root.children.end(); ++it) {
const Node* res = getLCA_Rec(**it, lhs, rhs, flag);
if (res != nullptr) {
return res;
}
if (flag == (LCAFlag::leftFound | LCAFlag::rightFound)) {
return &root;
}
}
return nullptr;
}
}
const Node* getLCA(const Node& root, const Node& lhs, const Node& rhs)
{
unsigned int flag = detail::LCAFlag::NoFound;
return detail::getLCA_Rec(root, lhs, rhs, flag);
}
這假設您的樹是一棵有根的樹,並且您可以容納一些額外的空間來存儲每個節點的高度和父指針。
該算法的效率為O(height),因此它取決於樹的平衡程度。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.