Cuatro formas de atravesar árboles binarios

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:

Copiar codigo

clase pública TreeNode {
    datos int públicos;
    public TreeNode leftChild;
    public TreeNode rightChild;

    Public TreeNode (int datos) {
        this.data = datos;
    }

}

Copiar codigo

Creemos un árbol binario:

Copiar codigo

/ **
     * 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;
    }

Copiar codigo

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:

Copiar codigo

/ **
     * 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);
    }

Copiar codigo

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:

Copiar codigo

/ **
     * 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);
    }

Copiar codigo

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:

Copiar codigo

/ **
     * 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 + "");
    }

Copiar codigo

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

  1. Primero solicite una nueva pila, regístrela como pila;
  2. Declare un nodo treeNode, deje que apunte al nodo;
  3. 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,
  4. Repita el paso 3 hasta que treenode esté vacío;
  5. Luego, abre la pila y deja que treeNode apunte al hijo derecho de treeNode
  6. Repita el paso 3 hasta que la pila esté vacía.

El código de implementación es el siguiente:

Copiar codigo

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;
            }
        }
    }

Copiar codigo

El recorrido de orden medio no es recursivo, por lo que no describiré los pasos específicos aquí.

Proceso específico:

  1. Solicite una nueva pila, regístrela como pila, solicite una variable cur e inicialmente establezca treeNode como el nodo principal;
  2. 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;
  3. 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;
  4. Finaliza cuando la pila está vacía y cur está vacía.

Copiar codigo

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;
            }

        }
    }

Copiar codigo

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.

Copiar codigo

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;
                }

            }

        }
    }

Copiar codigo

Finalmente, les presentaré el recorrido de la secuencia de capas

Los pasos específicos son los siguientes:

  1. Primero solicite una nueva cola y regístrela como cola;
  2. Presione la cabeza del nodo principal en la cola;
  3. 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;
  4. Repita el paso 3 hasta que la cola esté vacía.

El código de implementación es el siguiente:

Copiar codigo

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);
        }
    }

Copiar codigo

 

Categoría:  árbol

Supongo que te gusta

Origin blog.csdn.net/sd19871122/article/details/108075879
Recomendado
Clasificación