2017-07-27 19 views
2

我々はいくつかの場所でroot.leftroot.right変数に関数呼び出しの結果を格納する必要がないのはなぜ再帰:関数に渡された変数を追跡して更新する必要がありますか?

Node deleteRec(Node root, int key) 
    { 
     /* Base Case: If the tree is empty */ 
     if (root == null) return root; 

     /* Otherwise, recur down the tree */ 
     if (key < root.key) 
      root.left = deleteRec(root.left, key); 
     else if (key > root.key) 
      root.right = deleteRec(root.right, key); 

     // if key is same as root's key, then This is the node 
     // to be deleted 
     else 
     { 
      // node with only one child or no child 
      if (root.left == null) 
       return root.right; 
      else if (root.right == null) 
       return root.left; 

      // node with two children: Get the inorder successor (smallest 
      // in the right subtree) 
      root.key = minValue(root.right); 

      // Delete the inorder successor 
      root.right = deleteRec(root.right, root.key); 
     } 

     return root; 
    } 

を私はバイナリ検索ツリーからノードを削除するコードを行っていたと私は少し混乱しています? rootの値、つまり参照が関数に渡されているため、後続の呼び出しの変更によって自動的にツリーが更新されますが、そうではありませんか?なぜ変数に値を格納するのですか?以下の私のポイントを明確にするには、コード

// A recursive function used by topologicalSort 
void topologicalSortUtil(int v, boolean visited[], 
         Stack stack) 
{ 
    // Mark the current node as visited. 
    visited[v] = true; 
    Integer i; 

    // Recur for all the vertices adjacent to this 
    // vertex 
    Iterator<Integer> it = adj[v].iterator(); 
    while (it.hasNext()) 
    { 
     i = it.next(); 
     if (!visited[i]) 
      topologicalSortUtil(i, visited, stack); 
    } 

    // Push current vertex to stack which stores result 
    stack.push(new Integer(v)); 
} 

の別の部分は、スタックが関数に渡されると、我々はスタックは全体の更新を続けるだろうことを知っているので、我々は単にさらに関数呼び出しに何度も何度もそれを使用しています。ここでコール。

何か不足していますか間違ったことを理解しましたか?誰かが私の理解を助けてくれますか?ありがとう!!

答えて

1

ツリーのノードを削除すると、親ノードの左または右のポインタを更新する必要があります。最も単純なケースは、削除されたnotがリーフである場合です。その場合、それを指すリンクをnullに設定する必要があります。

さらに、削除されるノードがルートノードである場合は、ルートへのポインタを更新する必要があります。

deleteRecメソッドを呼び出すときに、返される値が最初のパラメータと同じになるかどうかを事前に知ることはできません。

+0

"最も単純なケースは、削除されたノードがリーフの場合です。その場合、そのノードを指すリンクをnullに設定する必要があります。答えをありがとう。すべての答えは役に立ちましたが、この行は私にはっきりと分かりました。乾杯! – varunkr

1

異なるレベルの再帰レベルのオブジェクトは同じオブジェクトではありません。

ツリーを再帰的に実行するときは、root.leftまたはroot.rightを最初の引数としてdeleteRecと呼び出します。したがって、次のレベルの再帰は、左または右のサブツリーのルートを「ルート」として扱います。

これは、topologicalSortUtilの3番目のパラメータで渡した変数とは異なります。この変数は常に変更されずにそのまま渡されるため、すべてのレベルで同じ正確なオブジェクトにアクセスできます。

1

ノードを削除するときは、ノードの下のツリーの部分をプルアップする必要があります。それ以外の場合は、ノードとその子孫ノードをすべて削除しますが、これは正しくありません。

1

deleteRecメソッドは、バイナリツリーのNodeを受け取り、ツリーを変更します。ただし、各再帰呼び出しには、ツリーの異なるNodeが渡されます。これは、同じ再帰呼び出しに同じStackが渡される、2番目の例とは異なります。今

deleteRecそれは(現在の再帰呼び出しのrootを削除すべきNodeある場合に発生する)木から削除する必要がありますNodeを見つけ、それが木からそのNodeを削除することはできません。ツリーからNodeを削除するには、削除したNodeの親のNodeを変更する必要があります。これは、再帰呼び出しが返ってくるときに起こります。その呼び出しによって返されたNodeは、root.leftまたはroot.rightのいずれかに割り当てられます。

関連する問題