Cuatro formas de recorrer el árbol binario:
- Atravesar el árbol binario se refiere a comenzar desde el nodo raíz, visitar todos los nodos del árbol binario en un orden determinado, de modo que cada nodo se visite secuencialmente y solo una vez.
Los cuatro métodos de recorrido son: recorrido de primer orden, recorrido de orden medio, recorrido posterior al orden y recorrido de orden de capa.
Antes de atravesar, primero presentamos cómo crear un árbol binario. Aquí usamos el método de construir el árbol de la izquierda primero y luego construir el árbol de la derecha.
Primero, debemos declarar el nodo de la clase TreeNode, el código es el siguiente:
clase pública TreeNode { datos int públicos; public TreeNode leftChild; public TreeNode rightChild; Public TreeNode (int datos) { this.data = datos; } }
Creemos un árbol binario:
/ ** * Construye un árbol binario * @param lista secuencia de entrada * @regreso * / public static TreeNode createBinaryTree (LinkedList <Integer> lista) { Nodo TreeNode = nulo; if (list == null || list.isEmpty ()) { devolver nulo; } Datos enteros = list.removeFirst (); si (datos! = nulo) { nodo = nuevo TreeNode (datos); node.leftChild = createBinaryTree (lista); node.rightChild = createBinaryTree (lista); } nodo de retorno; }
A continuación, explíquelos uno por uno en el orden indicado anteriormente,
Primero observe el recorrido de preorden El llamado recorrido de preorden consiste en visitar primero el nodo raíz, luego el nodo izquierdo y finalmente el nodo derecho.
Como se muestra en la figura anterior, el resultado del recorrido de preorden es: ABDFECGHI
El código de implementación es el siguiente:
/ ** * Raíz de recorrido de preorden de árbol binario -> izquierda -> derecha * @param node Nodo de árbol binario * / public static void preOrderTraveral (nodo TreeNode) { si (nodo == nulo) { regreso; } System.out.print (node.data + ""); preOrderTraveral (node.leftChild); preOrderTraveral (node.rightChild); }
El segundo es el recorrido de orden medio, el llamado recorrido de orden medio consiste en visitar primero el nodo izquierdo, luego el nodo raíz y finalmente el nodo derecho.
Como se muestra en la figura anterior, el resultado del recorrido de orden medio es: DBEFAGHCI
El código de implementación es el siguiente:
/ ** * Cruce de orden medio del árbol binario izquierda -> raíz -> derecha * @param node Nodo de árbol binario * / public static void inOrderTraveral (nodo TreeNode) { si (nodo == nulo) { regreso; } inOrderTraveral (node.leftChild); System.out.print (node.data + ""); inOrderTraveral (node.rightChild); }
El último es el recorrido posterior al pedido. El llamado recorrido posterior al pedido consiste en visitar primero el nodo izquierdo, luego el derecho y finalmente el nodo raíz.
Como se muestra en la figura anterior, el resultado transversal posterior al pedido es: DEFBHGICA
El código de implementación es el siguiente:
/ ** * Recorrido posterior al orden del árbol binario izquierda -> derecha -> raíz * @param node Nodo de árbol binario * / public static void postOrderTraveral (nodo TreeNode) { si (nodo == nulo) { regreso; } postOrderTraveral (node.leftChild); postOrderTraveral (node.rightChild); System.out.print (node.data + ""); }
Después de hablar sobre los tres métodos recursivos anteriores, hablemos de cómo se realiza el recorrido no recursivo.
Sigue siendo el mismo, primero mira el recorrido de preorden no recursivo
- Primero solicite una nueva pila, regístrela como pila;
- Declare un nodo treeNode, deje que apunte al nodo;
- Si treeNode no está vacío, imprima el valor de treeNode y empuje treeNode en la pila, y luego haga que treeNode apunte al nodo derecho de treeNode,
- Repita el paso 3 hasta que treenode esté vacío;
- Luego, abre la pila y deja que treeNode apunte al hijo derecho de treeNode
- Repita el paso 3 hasta que la pila esté vacía.
El código de implementación es el siguiente:
public static void preOrderTraveralWithStack (nodo TreeNode) { Stack <TreeNode> stack = new Stack <TreeNode> (); TreeNode treeNode = nodo; while (treeNode! = null ||! stack.isEmpty ()) { // Visite iterativamente el hijo izquierdo del nodo y combínelo en la pila while (treeNode! = null) { System.out.print (treeNode.data + ""); stack.push (treeNode); treeNode = treeNode.leftChild; } // Si el nodo no tiene un hijo izquierdo, abre el nodo superior de la pila y visita el hijo derecho del nodo if (! stack.isEmpty ()) { treeNode = stack.pop (); treeNode = treeNode.rightChild; } } }
El recorrido de orden medio no es recursivo, por lo que no describiré los pasos específicos aquí.
Proceso específico:
- Solicite una nueva pila, regístrela como pila, solicite una variable cur e inicialmente establezca treeNode como el nodo principal;
- Primero, inserte el nodo treeNode en la pila. Para todo el subárbol encabezado por el nodo treeNode, inserte el subárbol izquierdo de todo el árbol en la pila, es decir, mantenga treeNode = treeNode.leftChild, y luego repita el paso 2;
- Repita el paso 2 hasta que encuentre que cur está vacío. En este momento, un nodo emerge de la pila como treeNode, imprime el valor del nodo y deje treeNode = treeNode.right, y luego continúe repitiendo el paso 2;
- Finaliza cuando la pila está vacía y cur está vacía.
public static void inOrderTraveralWithStack (nodo TreeNode) { Stack <TreeNode> stack = new Stack <TreeNode> (); TreeNode treeNode = nodo; while (treeNode! = null ||! stack.isEmpty ()) { while (treeNode! = null) { stack.push (treeNode); treeNode = treeNode.leftChild; } if (! stack.isEmpty ()) { treeNode = stack.pop (); System.out.print (treeNode.data + ""); treeNode = treeNode.rightChild; } } }
El recorrido posterior al pedido no se implementa de forma recursiva. El recorrido posterior al pedido aquí es un poco más complicado que las dos implementaciones anteriores. Necesitamos un bit marcador para recordar un nodo en nuestro nodo en este momento. Consulte los comentarios del código para obtener más detalles.
public static void postOrderTraveralWithStack (nodo TreeNode) { Stack <TreeNode> stack = new Stack <TreeNode> (); TreeNode treeNode = nodo; TreeNode lastVisit = null; // Marque el último nodo visitado para cada recorrido while (treeNode! = null ||! stack.isEmpty ()) {// El nodo no está vacío, el nodo está en la pila y apunta al siguiente hijo izquierdo while (treeNode! = null) { stack.push (treeNode); treeNode = treeNode.leftChild; } // La pila no está vacía if (! stack.isEmpty ()) { //Halar treeNode = stack.pop (); / ** * Este bloque es para determinar si treeNode tiene un hijo correcto, * Si no se muestra treeNode.data, deje que lastVisit apunte a treeNode y deje que treeNode esté vacío * Si hay un hijo correcto, continúe con el nodo actual en la pila, treeNode apunta a su hijo derecho y continúe repitiendo el ciclo * / if (treeNode.rightChild == null || treeNode.rightChild == lastVisit) { System.out.print (treeNode.data + ""); lastVisit = treeNode; treeNode = null; }más{ stack.push (treeNode); treeNode = treeNode.rightChild; } } } }
Finalmente, les presentaré el recorrido de la secuencia de capas
Los pasos específicos son los siguientes:
- Primero solicite una nueva cola y regístrela como cola;
- Presione la cabeza del nodo principal en la cola;
- Cada vez que abandone la cola, regístrelo como nodo y luego imprima el valor del nodo. Si el hijo izquierdo del nodo no está vacío, el hijo izquierdo se pondrá en cola; si el hijo derecho del nodo no está vacío, el hijo derecho se pondrá en cola;
- Repita el paso 3 hasta que la cola esté vacía.
El código de implementación es el siguiente:
public static void levelOrder (TreeNode root) { LinkedList <TreeNode> cola = nueva LinkedList <> (); queue.add (raíz); while (! queue.isEmpty ()) { raíz = cola.pop (); System.out.print (root.data + ""); if (root.leftChild! = null) queue.add (root.leftChild); if (root.rightChild! = null) queue.add (root.rightChild); } }
Categoría: árbol