2016-09-23 2 views
1

私は各親ノードに複数の息子を入れることができ、それぞれの息子には親が1人しかいないようなツリー構造で作業しています。ファイルシステム内のディレクトリ構造。ソフトウェア設計パターン:親に息子を追加し、親を息子に割り当てます。

私はこれらの多くを行っていますが、私は今あなたと共有しようとしているよりも、鶏と卵の問題を解決するためのさまざまなアプローチがありますが、それを解決するために私が今まで無視してきたパターン。

親を息子ノードに設定すると、親はこの新しいノードをその子孫リストに追加しなければならず、息子を親に追加すると、息子はその親を更新しなければならず、すべてが一貫性のある木を維持するために、そうでなければ父親として認識しない息子を持つ両親に終わる可能性があります...

例を見てみましょう(JAVA )、コードの問題のために、より良いコードに示されている段落で説明したよりも:そこのarが

class Node { 
    private Node parent; 
    private ArrayList<Node> sons=new ArrayList<Node>(); 

    public void setParent(Node parent) { 
     this.parent = parent; 
     parent.addSon(this); 
    } 

    public void addSon(Node son) { 
     this.sons.add(son); 
     son.setParent(this); 
    } 

} 

OK、これは、簡単のため、最も単純な形式であります他の対処すべき事柄(例えば、前の親からの息子の削除)。私はあなたが既にここにある再帰的な問題を既に見ていると確信しています。

多かれ少なかれ明白なアプローチは、息子はすでに親としてこれを割り当てられているかどうかを実行時にチェックすることですので、私はとしてこれらのメソッドを書き換えたい:

public void addSon(Node son) { 
     this.sons.add(son); 
     if (son.parent != this) 
      son.setParent(this); 
    } 

でも存在することになるのだろうかこれを解決するより良いアプローチ。例えば、いくつかの冗長な呼び出しを節約する別のアプローチは、静的メソッドを使用して可能性があり、何かのように:だから、提供assignSon一つは、自分の父親に息子を関連付けるために使用できる唯一の方法である

class Node { 
    private Node parent; 
    private ArrayList<Node> sons=new ArrayList<Node>(); 

    public static assignSon(Node parent, Node son) { 
     parent.sons.add(son); 
     son.parent = parent; 
    } 
} 

、これは鶏を解決します-an-卵の問題が、あなたのような何かを行うことができます前に、どこ、あなたが知っている、それが外部から利用することも何とかあまり直感的であり、そして、あなたはより多くのコードを記述する必要があります:

son.setParent(parent); 

それとも

parent.addSon(son); 

あなたが今書くことでしょう:

Node.assignSon(parent, son); 

をそれは大したことではないのですが、それでも...よく、何でも。あなたがこの問題の最適なアプローチを知っていて、あなたがこのコミュニティと共有したいのであれば、私は1人に非常に感謝します!

TIA!

答えて

1

私は @uoyilmaz と同じコードで行くが、古い親(すでに存在する場合)を更新することを忘れないでください、あなたはすでに他の誰かに割り当てられた息子を割り当てている場合はそうでないあなたには、いくつかの矛盾を取得するでしょう。例えば

このツリーからの場合:b

a 
/\ 
b c 
| 
d 

aの息子として

a 
/| \ 
b c d 

あなたがdを移動するには、まだdノードへの参照を持つことになります。

そのため、おそらくこのようなものが動作するはずです:

class Node { 
    private Node parent; 
    private ArrayList<Node> sons=new ArrayList<Node>(); 

    private void setParent(Node parent) { 
     this.parent = parent; 
    } 

    public void addSon(Node son) { 
     if(!this.sons.contains(son)) { 
      this.sons.add(son); 

      if(son.parent != null) { 
       son.parent.sons.remove(son); 
      } 

      son.setParent(this); 
     } 
    } 
} 
+0

あなたの 'removeSon'メソッドでは' son'の親を扱わなければなりません。あなたは親から息子を取り除いているので、「息子」はそれを認識していません。 –

+1

どういう意味ですか?オブジェクトの観点から 'removeSon'を見なければならないので、メソッドは"私 "(もし存在すれば)から息子を取り除いています。このメソッドは 'addSon'メソッドで息子の親から呼び出されます。私がやっていることは、「大丈夫、「b」の子として「d」を追加しています。「b.addSon(d)」、「ehy'd」です。 " 「はい、それは「a」なのでnullではありません。 "ああ、クール、私を許してください、あなたはあなたの息子から" d "を取り除くことができますか?" - > 'd.parent.removeSon(d)'。 – Enrichman

+0

@Enrichmanこれは本当にうまく見えますが、ここでも2つの問題があります。まず、単純にこれを扱っていないかもしれませんが、とにかくaddSonメソッド内では、まず息子リストにその息子がいないことを確認する必要があります。そうしないと、もう一度息子となりますそれは父親を知っているが、息子を認めない父親である。そして、2番目に、removeSonメソッドpublicと最後のツリーを取って、そのクラスの外からremoveSon(b)を呼び出すとしましょう。その時点から 'a'は 'b'について何も知らないでしょうが、 'b' aは彼の父親です。 –

1

私は、鶏肉と卵の問題を避けるため、setParentを呼び出すaddSonメソッドを書くことができます。逆も同様ですが、以下のように両方向ではありません。私はツリーの上に行く方法を実装する必要があるとき、私は一貫してそれをツリーに使用します。

class Node { 
    private Node parent; 
    private ArrayList<Node> sons=new ArrayList<Node>(); 

    private void setParent(Node parent) { 
     this.parent = parent; 
    } 

    public void addSon(Node son) { 
     this.sons.add(son); 
     son.setParent(this); 
    } 
} 
+0

別のアプローチだと確かにそれは鶏と卵の問題を破るが、欠点は、これは、非コヒーレント状態で木を残したことができるということですとても簡単に。あなたは知っている、あなたは親を持つ息子に終わることができるが、親はその息子について何も知らない。 –

+1

実際には、ノードをツリーに追加するときにaddSonメソッドを呼び出すだけです。あなたは最初に息子を親に追加し、親を息子に登録します。私は、それを親として認識する息子について何も知らない親で終わることができるシナリオを見つけることができません。 – uoyilmaz

+0

なぜ、息子は親について何も知らないのですか? 'this'は与えられた親であり、' this.sons'は彼が持つ息子の配列です。だから彼は彼の息子は彼がいないことを知っていますか?それとも、ここで何かを実現するにはあまりにも疲れています。 – xetra11

関連する問題