2016-06-17 6 views
3

私は、バイナリ検索ツリーに要素を追加するために、このJava再帰的なプログラムを発見した:それは最後のnを返してから、再度rootにそれを割り当てることがある理由を私は理解していないものをどのようにこの再帰関数をトレースするには?

public void add(int e){ 
    root=add(root, e); 
} 
public Node add(Node n, int e){ 
    if (n==null){ 
     n=new Node(e); 
    } else { 
     if (e<n.elem){ 
      n.left=add(n.left,e); 
     } else{ 
      n.right=add(n.right,e); 
     } 
    } 
    return n; 
} 

です。 助けてください?

+1

最後の 'return n'文は、左と右への再帰呼び出しが終了した後に呼び出されます。再帰を扱うチュートリアル(または教科書)を見直さなければなりません。 –

+1

これを理解する最善の方法は、鉛筆と紙でそれを行い、空の木から始めることです。次に、コードをトレースし、値2,4、1、5を追加します。 'root'は最初の呼び出しでのみ実際のツリールートを参照します。その後、複数のレベルが下がると、 'root'は現在のサブツリーのルートを参照します。 –

答えて

4

割り当ての理由は、Javaには値渡しのパラメータを渡す方法が1つしかないからです。

rootへの参照は、値によってaddに渡されます。ただし、addはルートに渡されたノードを変更する必要があります。たとえば、最初のノードをツリーに追加する場合、rootの値はnullですが、ノードを追加した後はnullになる必要があります。

この制限を回避するイディオムは、変更された値を返すメソッドを作成し、それをパラメータに戻すことです。 if (n==null) n=new Node(e);:それはあなたが再帰を理解したい場合は、あなたのadd方法がここに

root=add(root,e); 

、ここ

n.left = add(n.left, e); 
n.right = add(n.right, e); 
+0

アルゴリズムのこのバージョンはより良いと考えられますか、ヌルをチェックし、それに応じて動作します。 – HopefullyHelpful

+0

@HopefullyHelpfulあなたは代入なしで行うことができますが、3つの場所、つまりトップレベルの 'void add'と条件付きの両方の枝で' null'チェックする必要があります。一方、この実装では、単一の「ヌル」チェックがあるため、より短くなります。 – dasblinkenlight

0

をやっていることで、あなたはそれを終了する条件を見てする必要があります。

これは、Node nnullの場合に最後のコールが行われることを意味します。いつになりますか?葉の一つに。その後、ツリーに追加される別のオブジェクトが作成されます。その後

、それはreturn nの論理だけです:最後の呼び出しの後、nです:new Node(e)。新しいNodeは誰に割り当てられますか?一部の(元)葉のn.leftまたはn.right。スタック内のメソッドaddへの最初の呼び出しに達するまで、同じロジックがツリーの上に沈みます。それは完全に更新されたツリー、つまりあなたが望む最終製品を返します。

関連する問題