【问题标题】:Checking for node repetition in multi-parent tree检查多父树中的节点重复
【发布时间】:2012-04-02 15:58:36
【问题描述】:

我在 SQL 中有一个非常简单的树实现:

CREATE TABLE [dbo].[Nodes] (
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](max) NULL
);

CREATE TABLE [dbo].[NodeNodes] (
    [ParentNodeId] [int] NOT NULL,
    [ChildNodeId] [int] NOT NULL
);

我的树实现是一个节点可以有多个父节点。这样用户就可以创建自定义树,将常用节点组合在一起。例如:

      1              8         9
    /   \           / \       / \
   2     3         4   7     2   6
  / \   / \                 / \
 4   5 6   7               4   5

Node | Parents | Children
---------------------------
  1  |    -    |   2,3
  2  |   1,9   |   4,5
  3  |    1    |   6,7
  4  |   2,8   |    -
  5  |    2    |    -
  6  |   3,9   |    -
  7  |   3,8   |    -
  8  |    -    |   4,7
  9  |    -    |   2,6

所以有三棵树,由没有父节点的三个节点表示。我的问题是当用户将节点添加为另一个节点时验证潜在关系。我不希望节点在同一棵树中出现两次。例如,将节点 2 添加为节点 6 的子节点应该会失败,因为这会导致节点 2 在 1 的树和 9 的树中出现两次。我在编写执行此操作的有效算法时遇到了麻烦。

我的第一个想法是找到准父母的所有根,将根的树展平以获得每棵树的一个节点列表,然后将这些列表与准孩子相交,最后只有当所有结果相交列表为空。用这个例子,我会得到这些步骤:

1) Trace prospective parent through all parents to roots:
6->3->1
6->9

2) Flatten trees of the roots
1: {1,2,3,4,5,6,7}
9: {2,4,5,6,9}

3) Intersect lists with the prospective child
1: {1,2,3,4,5,6,7}^{2} = {2}
9: {2,4,5,6,9}^{2} = {2}

4) Only pass if all result lists are empty
1: {2} != {} ; fail
9: {2} != {} ; fail

此过程有效,但它需要将整棵树放入内存中。我有一些具有 20,000 多个节点的树,这需要将近一分钟的时间来运行。这种表现不是 100% 破坏交易,但它非常令人沮丧。有没有更有效的算法来做到这一点?

编辑 4/2 下午 2 点

上述算法实际上不起作用。 deroby 指出,将 9 作为孩子添加到 7 将由算法传递,但不应该传递。问题是只要节点不重复,将具有子节点的节点添加到另一个节点就会成功——它不会验证子节点。

【问题讨论】:

  • 只是为了确定我理解正确:因此在示例中将 9 作为孩子添加到 7 就可以了吗?
  • 将 9 作为孩子添加到 7 违反了我想要做的事情,因为 9 的所有孩子最终都会重复,但使用上面的算法并没有发现它。因此,如果您要添加叶节点,上述算法似乎可以正常工作,但如果您尝试添加具有子节点的节点,它不会验证子节点。
  • 当您说“节点 2”时,您的意思是“节点表中 Id(列)值为 2 的行”吗?
  • 是的,所有的数字都是指节点ID。
  • 我想知道解决方案是否有问题-您要解决什么问题?

标签: sql-server tree


【解决方案1】:

一年后,我偶然发现了自己的问题,我决定添加我的解决方案。原来我刚刚忘记了我的基本数据结构。 我原本以为简单的树其实是有向图,而我测试的是一个循环。鉴于循环检测是一件非常普遍的事情,互联网上应该有大量的解决方案和讨论。一个例子请参见Best algorithm for detecting cycles in a directed graph

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多