查找两个叶节点的最佳公共祖先,其中节点有零个、一个或两个父节点

发布于 2024-11-09 08:55:20 字数 1126 浏览 0 评论 0原文

目标

我正在寻找一种算法来找到图的最佳共同祖先,其中图中的节点可以有零个、一个或两个父节点。我不确定“最佳共同祖先”的术语:更好的术语可能是“最低共同祖先”或“最近共同祖先”等。如果有更好的术语,请提供描述此类术语的 URL。

该算法可以访问完整的图数据结构。

给定节点可能有零个、一个或两个父节点。这是关键,因为我在网上看到的算法假设给定节点有零个或一个父节点,但没有两个父节点(请参阅下面的参考资料)。例如,下图中的 m1 节点有零个父节点,因为它是根(图中可以有多个根)。 d3 有两个父母,一个是 d2,另一个是 b2。

节点具有对双亲(如果存在)的引用,以及对所有子节点(如果存在)的引用,因此向上和向下遍历树是公平的游戏。节点可以有零个或多个子节点。改变数据结构不是一个选择。

靠近两个输入节点的节点比距离较远的节点(即,更靠近图的根)更可取。

例如,下图显示了一种可能的图表。在这种情况下,算法的输入将是节点 b5 和 d4。节点 b5 和 d4 的最佳公共祖先是 b2。 c2 不会,因为 b3 属于通向 b5 的谱系。

该算法的可能答案最多只能是一个节点,并且在两个输入节点没有共同祖先的情况下,空集是有效答案。

参考资料

Tarjan 离线最不常见祖先算法 似乎意味着零个或一个父母,所以如果这是解决方案,那么答案应该包括如何在该算法中考虑两个父母的描述。 最低共同祖先的维基百科页面似乎也只考虑节点具有零或零的数据结构一位父母,而不是两位:

在树形数据结构中,每个 节点指向其父节点,...

图表

graph graph

Goal:

I am looking for an algorithm to find the best common ancestor of a graph where nodes in the graph can have zero, one, or two parents. I am not sure of the terminology of "best common ancestor": better terminology might be "lowest common ancestor", or "recent common ancestor", etc. If there is better terminology then please provide URL's that describe such.

The algorithm has access to the full graph data structure.

It is possible for a given node to have zero, one, or two parents. This is key because the algorithms I've seen on the web assume that a given node has either zero or one parents, but not two parents (see references below). For instance, the m1 node in the diagram below has zero parents as it is the root (there can be multiple roots of the graphs). d3 has two parents, one is d2 and the other b2.

Nodes have references to both parents if they exist, and references to all children, if they exist, so traversal up the tree and down the tree is fair game. Nodes can have zero or more children. Changing the data structure is not an option.

Nodes closer to the two input nodes are preferable than nodes farther away (i.e., closer to roots of the graph).

By example, one possible graph is shown by the diagram given below. In this scenario, the inputs to the algorithm would be nodes b5 and d4. The best common ancestor of nodes b5 and d4 is b2. c2 would not be because b3 is in the lineage leading to b5.

Possible answers for the algorithm can be at most one node, and the empty set is a valid answer in the case that there is no common ancestor of the two input nodes.

Reference Material

Tarjan's off-line least common ancestors algorithm seems to imply zero or one parents, so if that is the solution, then the answer should include a description of how two parents are accounted for in that algorithm. The wikipedia page for Lowest common ancestor also seems to only account for data structures whose nodes have zero or one parents, not two:

In a tree data structure where each
node points to its parent, ...

Diagram:

graph diagram

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心碎无痕… 2024-11-16 08:55:20

我经营一个家谱网站,我之前用以下算法解决了这个问题。

对于两个节点,使用递归生成一个数组,该数组将节点名称与生成链接起来。以您的示例为例,b4 是 b5 的 1 代; b3为2代;等:

$b5Tree = array('b4'=>1, 'b3'=>2, 'c3'=>2, 'b2'=>3, 'c2'=>3, ...);
$d4Tree = array('d3'=>1, 'b2'=>2, 'd2'=>2, 'b1'=>3, 'd1'=>3, ...);

基本情况是检查第一个节点是否出现在第二个树中,反之亦然。如果它存在,那么你就有了答案。

否则,迭代一棵树,查找公共节点 ID,并跟踪最小代。

$minNodeID = null;
foreach ($b5Tree as $nID => $gen)
{
    if (($d4Tree[$nID] != 0) and (($d4Tree[$nID]  + $gen) < $minSummedGen))
    {
        $minSummedGen = $d4Tree[$nID] + $gen;
        $minNodeID = $nID;
    }
}
return $minNodeID;

I run a genealogy website, and I've solved this problem before with the following algorithm.

For both nodes, use recursion to generate an array which links node name with generation. Using your example, b4 is 1 generation above b5; b3 is 2 generations; etc:

$b5Tree = array('b4'=>1, 'b3'=>2, 'c3'=>2, 'b2'=>3, 'c2'=>3, ...);
$d4Tree = array('d3'=>1, 'b2'=>2, 'd2'=>2, 'b1'=>3, 'd1'=>3, ...);

The base case is to check if the first node appears in the second's tree, and vice-versa. If it exists, then you have your answer.

Otherwise, iterate through one of the trees, finding common node IDs, and keeping track of the minimum generation.

$minNodeID = null;
foreach ($b5Tree as $nID => $gen)
{
    if (($d4Tree[$nID] != 0) and (($d4Tree[$nID]  + $gen) < $minSummedGen))
    {
        $minSummedGen = $d4Tree[$nID] + $gen;
        $minNodeID = $nID;
    }
}
return $minNodeID;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文