【发布时间】:2012-06-01 14:47:09
【问题描述】:
假设我有一个代表嵌套集层次结构的节点列表(示例在伪 c# 中)。
class Node
{
public decimal left;
public decimal right;
public decimal id;
public void AddChild(Node child) {...}
...
}
List<Node> nodes = GetFlatNodesWithoutChildrenSetFromDatabase();
left、right 和 id 字段被填满,因为这些值存储在某个数据库中。
将这个平面列表转换为层次结构的有效方法是什么,这意味着为每个父节点填充适当的子节点?
一种方法是找到每个节点的所有祖先,对它们进行排序以找到父节点并将子节点添加到该节点。
foreach (var n in nodes)
{
var parent = nodes.Where(i => i.left < n.left && i.right > n.right).OrderBy(i => i.right - n.right).FirstOrDefault();
if (parent != null)
parent.AddChild(n);
}
但这是相当低效的。
有没有更好(即更快)的方法?
编辑
可能的解决方案(as suggested by Chris):
var stack = new Stack<Node>(nodes.Take(1));
foreach (var n in nodes.Skip(1))
{
while (stack.Peek().right < n.left)
stack.Pop();
stack.Peek().addChild(n);
stack.Push(n);
}
节点必须按left 排序。
【问题讨论】:
-
left和right是否以某种方式代表孩子? -
是的,我发现很难弄清楚你在用 left 和 right 做什么来获得父节点......
-
左右是描述节点在嵌套集合层次结构中的位置的数字en.wikipedia.org/wiki/Nested_set_model
-
对,所以问题本质上是:你有一个
(leftindex, rightindex, key)三元组列表,你想要一个(leftpointer, rightpointer, key)节点树?
标签: algorithm nested-sets