2012-04-02 10 views
0
私は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 

したがって、3つのノードは3つのノードで表示され、親はありません。私の問題は、ユーザーがノードを別のノードとして追加したときの潜在的な関係を検証することです。同じツリーにノードが2回表示されないようにしたいと思います。たとえば、ノード2を1のツリーおよび9のツリーに2回表示させるため、ノード2をノード6の子として追加すると失敗するはずです。私はこれを行う効率的なアルゴリズムを書くのに問題があります。

私の最初のアイデアは、見込みのある親のすべてのルートを見つけて、ルートごとのツリーを平坦化して、ツリーごとのノードのリストを取得し、それらのリストを将来の子と交差させ、結果として生じる交差リストのうちの1つは空である。例と一緒に行く、私はこれらの手順を取得したい:

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 

このプロセスは、それが全体をメモリに木を置く必要とするという事実を除いて、動作します。私は2万以上のノードを持ついくつかの木を持っており、これは実行するのに約1分かかります。このパフォーマンスは100%のデベロッパーではありませんが、非常にイライラです。これを行うより効率的なアルゴリズムはありますか?

編集は4/2 14:00

上記のアルゴリズムは、実際には動作しません。 derobyは、7に子として9を加えることはアルゴリズムによって渡されるが、そうであってはならないことを指摘した。問題は、子を持つノードを別のノードに追加することは、ノードが繰り返されない限り成功し、子ノードを検証しないことです。

+0

私は物事を正しく理解していることを確信しています。つまり、9に9を加えて7にすると、この例では問題ありませんか? – deroby

+0

9人の子供を7人に追加すると、9人の子供のすべてが繰り返されてしまうので、私がやろうとしていることに違反しますが、上記のアルゴリズムを使用していると捕らえられません。したがって、上記のアルゴリズムは、リーフノードを追加する場合はうまく動作しますが、ノードを子ノードとともに追加しようとしている場合、子ノードを検証しません。 – ptorian

+0

「ノード2」と言うと、「ノード2のID(列)に値2の行」という意味ですか? –

答えて

0

1年後、私は自分の質問に遭遇し、解決策を追加することに決めました。私は基本的なデータ構造を忘れてしまったことが分かります。 私が元々考えていたのは、単純な木は実際には有向グラフで、私がテストしていたのはサイクルでした。サイクル検出が非常に一般的なものであることを見ると、そこにはインターネット上で多数の解決策やディスカッションが存在するはずです。 1つの例については、Best algorithm for detecting cycles in a directed graphを参照してください。