2010-02-11 15 views
5

Sto cercando di tracciare il percorso di un nodo in un albero binario (non un albero di ricerca binario). Dato un nodo, sto provando a stampare i valori del percorso dalla radice.Hai bisogno di aiuto per tornare da un metodo ricorsivo

alt text

Ho scritto il seguente programma.

package dsa.tree; 

import java.util.Stack; 

public class TracePath { 
    private Node n1; 

    public static void main(String args[]){ 
     TracePath nodeFinder = new TracePath(); 
     nodeFinder.find(); 
    } 

    public void find(){ 
     Tree t = getSampleTree(); 
     tracePath(t,n1); 
    } 

    private Tree getSampleTree() { 
     Tree bsTree = new BinarySearchTree(); 
     int randomData[] = {43,887,11,3,8,33,6,0,46,32,78,76,334,45}; 
     for(int i=0;i<randomData.length;i++){ 
      bsTree.add(randomData[i]); 
     } 
     n1 = bsTree.search(76); 
     return bsTree; 
    } 

    public void tracePath(Tree t, Node node){ 
     trace(t,node); 
    } 

    Stack<Node> mainStack = new Stack<Node>(); 

    public void trace(Tree t, Node node){ 
     trace(t.getRoot(),node); 
    } 

    private void trace(Node parent, Node node){ 
     mainStack.push(parent); 
     if(node.data == parent.data){ 
      for(Node iNode:mainStack){ 
       System.out.println(iNode.data); 
      } 
      return; 
     } 
     if(parent.left != null){ 
      trace(parent.left, node); 
     } 
     if(parent.right!=null){ 
      trace(parent.right, node); 
     } 
     mainStack.pop(); 
    } 
} 

Sto ottenendo l'uscita correttamente. Ma è un po 'disordinato. Se vedi il metodo trace (Node, Node), sto stampando i valori che non dovrei fare. Voglio che il metodo trace sia completato correttamente. Almeno, dovrei uccidere la struttura ricorsiva nello stadio in cui incontro la condizione if.

Si prega di avvisare.

risposta

5

OK, è necessario eliminare la ricorsione una volta trovato il nodo. Abbastanza semplice Cambia il tuo metodo di traccia per restituire un booleano che ci dice se il nodo è stato trovato. In questo modo, torniamo subito all'albero subito dopo aver trovato il nodo.

private boolean trace(Node parent, Node node){ 
    mainStack.push(parent); 
    if(node.data == parent.data){ 
     for(Node iNode:mainStack){ 
      System.out.println(iNode.data); 
     } 
     return true; 
    } 
    if(parent.left != null){ 
     if (trace(parent.left, node)) return true; 
    } 
    if(parent.right!=null){ 
     if (trace(parent.right, node)) return true; 
    } 
    mainStack.pop(); 
    return false; 
} 
+0

Eccellente !!! Grazie mille .. Ora ho sperimentato come terminare/uscire dal metodo ricorsivo .. Grazie ancora! – bragboy

+0

Ora che hai dato una "soluzione" invece di un suggerimento per i compiti, modifico la mia risposta per mostrare cosa intendevo. – rsp

+0

Soluzione postata su: http://www.technicalypto.com/2010/02/trace-path-of-binary-tree.html Grazie. – bragboy

3

Presumo che questo è compito, quindi fornirò alcuni puntatori anziché un codice.

  • il metodo di traccia non una discesa ricorsiva, quindi lo stack non è necessaria - si può costruire la struttura del percorso mentre tornava da un nodo trovato
  • se il metodo utilizza un valore di ritorno booleano o elenco, è possibile stampare il percorso mentre tornava, o di costruire una lista con i nodi per stampare dopo che il metodo di ricerca restituisce

Edit: Se il nodo percorso radice è voluto, un semplice ritorno booleano basta:

0.123.
private boolean trace(Node parent, Node node) { 
    boolean found = (node.data == parent.data) 

    if (!found && parent.left != null) { 
     found = trace(parent.left, node); 
    } 
    if (!found && parent.right != null){ 
     found = trace(parent.right, node); 
    } 

    if (found) { 
     System.out.println(parent.data); 
    } 

    return found; 
} 

Se è necessario il percorso dalla radice al nodo, è possibile passare un elenco per ricevere i nodi in ordine:

private boolean trace(Node parent, Node node, List path) { 
    boolean found = (node.data == parent.data) 

    if (!found && parent.left != null) { 
     found = trace(parent.left, node); 
    } 
    if (!found && parent.right != null){ 
     found = trace(parent.right, node); 
    } 

    if (found) { 
     path.add(0, parent); 
    } 

    return found; 
} 

in alternativa si può costruire il percorso sulla via del ritorno e di ritorno, una lista.

private List trace(Node parent, Node node) { 
    List path = null; 

    if (null != node) { 
     if (node.data == parent.data) { 

      path = new ArrayList(); 
     } else { 
      path = trace(parent.left, node); 

      if (null == path) { 
       path = trace(parent.right, node); 
      } 
     } 
     if (null != path) { 
      path.add(0, parent); 
     } 
    } 
    return path; 
} 
+0

Grazie per suggerimenti .. Il mio dubbio è come terminare questo programma? – bragboy

+0

Ti sbagli, ha bisogno dello stack. Se si sbarazza e stampa solo, stampa la foglia, quindi il genitore della foglia, poi il genitore, torna alla radice. Ha bisogno del retro di quello stampato, quindi lo Stack è necessario per memorizzare il percorso. – Schmelter

+0

@Schmelter, ho fornito 2 possibili valori di ritorno, un valore booleano quando si desidera il nodo su root o un elenco che viene creato quando il nodo viene trovato in altro modo. Uno stack che riceve tutti i nodi non richiede le visite dell'algoritmo. – rsp

0

Ritorna un valore booleano da traccia e decidere se continuare o meno la ricerca in base al valore viene restituito dalla chiamata ricorsiva.

1

Qualcosa di simile?

public Stack<Node> findPath(Node src, Node dest, Stack<Node> alreadyCollected) { 
    if (src == dest) 
     return alreadyCollected; 
    if (src.left == null && src.right == null) 
     return null; 
    if (src.left != null) { 
     Stack<Node> toTheLeft = new Stack<Node>(alreadyCollected); 
     toTheLeft.push(src.left); 
     Stack<Node> result = findPath(src.left, dest, toTheLeft); 
     if (result != null) 
      return result; 
    } 
    List<Node> toTheRight = new Stack<Node>(alreadyCollected); 
    return findPath(src.right, dest, toTheRight); 
} 
+0

Grazie per la risposta. sento che stai creando troppi nuovi Stack() all'interno di un ciclo ricorsivo. Sembra costoso per me. – bragboy

+0

Penso che tu abbia ragione ;-) – Hubert

1

Ecco una funzione ricorsiva senza alcun utilizzo di stack. Una ricorsione equivale a impilare tecnicamente e non è necessario impilare quando si fa il recustion.

PS: Sto scrivendo uno pseudo codice. Riscrivilo tu stesso per farlo compilare :)

bool trace(Node curr, Node n, Path path){ 
    if(curr == null) 
     return; 
    if(n == curr){ 
     path.insertAtEnd(curr); 
     return true; 
    } 

    if(trace(curr.left, n, path)){ 
     path.insertAtEnd(curr); 
     return true; 
    } 
    if(trace(curr.right, n, path)){ 
     path.insertAtEnd(curr); 
     return true; 
    } 
    return false 
} 
+0

Il percorso variabile è solo un array e non viene utilizzato come stack (LIFO). –

+0

Il tuo codice funziona senza problemi !!!! Grazie mille Niraj .. Sì, lo stack fa un'operazione extra pop che non è necessaria quando questo può essere fatto in questo modo. – bragboy

+0

Cordiali saluti, il codice convertito sembra traccia booleano privato (Node curr, Nodo n, Lista percorso) { \t se (curr == null) \t return false; \t if (n == curr) { \t path.add (curr); \t return true; } \t if (traccia (curr.left, n, path)) { \t path.add (curr); \t return true; \t} \t if (trace (curr.right, n, path)) { \t path.add (curr); \t return true; \t} \t ritorno falso; \t} – bragboy

Problemi correlati