用于查找不是父/祖父/ /等或子/孙/等的所有链接对象的算法

时间:2011-09-09 04:42:57

标签: c# algorithm recursion

我有一个名为Device的对象。 Device可以包含一个父级 DeviceDevice也可以包含 n Devices

我有一个下拉列表,显示所有可选的Devices。我可以非常轻松地获取数据库中的所有Devices - db.Devices

层次结构可以是无限级别。

我需要所有Devices不高于或低于树中给定Device 的所有Devices。基本上我要求Device与给定的Device无关(父母/祖父母/祖父母/祖父母/等或儿童/孙子/曾孙子等)。我还需要从列表中排除给定的{{1}}。

最好的方法是什么?我应该使用递归吗?

(我正在使用带有SQL Server数据库的C#和Entity Framework,因此我可以使用Linq To SQL或使用模型本身。)

5 个答案:

答案 0 :(得分:3)

我的方法是首先获得设备D的所有兄弟姐妹:

P = parent of the device
sibs = {all children of P that are not D}

任何d in sibs的后代都与D无关。继续走上家谱:

G = grandparent of the device
sibs = sibs union {all children of G that are not P}

继续这样,集合sibs及其所有后代就是你所追求的集合。

在伪代码中:

D = device;
siblings = {};
while (D has parent) {
    P = parent(D);
    siblings = siblings union (children(P) \ D);
    D = P;
}
return descendants(siblings);

答案 1 :(得分:1)

同意Denis - 这取决于您的数据存储方式。

我建议您使用TSQL HierarchyId datatype实现层次结构。然后,您可以使用IsDescendent

非常轻松地检查行是否是另一行的后代
DECLARE @searchId HierarchyId -- select your id
SELECT @searchId = HierarchyId FROM Devices WHERE DeviceId = 1

SELECT * FROM Devices 
WHERE 
    -- not children
    DeviceHierarchyId.IsDescendantOf(@seachId) = 0
    -- not parents
    AND @searchId.IsDescendantOf(DeviceHierarchyId) = 0

修改

要简要说明HierarchyId数据类型及其工作原理,请考虑每个项目在根节点下的层次结构中都有一个位置。 (如果您有多个自然根,则将每个根放在超级根下)。每个hierarchyid列存储item的完整层次结构位置。例如

Id | ParentId | HierarchyId
1 | null | \1
2 | 1    | \1\2
3 | 1    | \1\3
4 | 3    | \1\3\4

等等。要检查项目是否是另一个项目的子项,只需检查hierarchyId是否包含在另一行的hierarchyId中 - 例如4是3的子项,因为整个\1\3包含在其hierarchyId \1\3\4中,但4不是2的子项,因为\1\2未包含在hierarchyId中。

要查看itemA是否为itemB的,请检查itemB是否为itemA的子项。

最后,您实际上不需要进行任何比较。 TSQL HierarchyId类型包含许多方法,其中一种方法是我在上面突出显示的IsDescendantOf方法。因此像hierarcyId1.IsDescendantOf(hierarchyId2)这样的用法会执行我在此处描述的那种检查。 hierarchyIds是二进制的,可以在数据库中快速比较。

在处理数据库层次结构时,我会尽可能使用hierarchyId。

答案 2 :(得分:0)

如果父母有索引,可以尝试

select * 
from devices as child 
where exists(select null 
                 from devices as parent 
                 where parent.id = child.parent)

我的SQL并不完美,但这是我将使用的基本方法。

答案 3 :(得分:0)

这取决于您将树存储在数据库中的方式。有nested sets model允许直接在数据库中进行此类查询。

答案 4 :(得分:0)

我的下意识算法解决方案是一种“标记 - 扫描”类型的解决方案(来自垃圾收集器理论)。

http://en.wikipedia.org/wiki/Garbage_collection_(computer_science)#Na.C3.AFve_mark-and-sweep

基本上你遍历整个设备层次结构并标记那些“可追踪”的设备,这意味着它们可以通过另一个设备“使用递归”到达。

任何未标记的内容,您都会“扫描”GC。在您的情况下,任何未标记的是您正在寻找的集合。