Búsqueda transversal del árbol de búsqueda binaria (implementación de Java)

1. El concepto de
árbol de búsqueda binaria Un árbol de búsqueda binario está organizado por un árbol binario, que puede ser representado por una estructura de datos de lista enlazada, donde cada nodo es un objeto.
Inserte la descripción de la imagen aquí

2. Los atributos del objeto del nodo del árbol de búsqueda binaria
(1) clave (palabra clave, utilizada para representar el objeto completo)
(2) Datos e información básicos
(3) izquierda, derecha yp, respectivamente apuntando al nodo secundario izquierdo del nodo , Nodo hijo derecho, nodo padre (si el nodo padre se usa menos, se puede omitir)

 class TreeNode {
    
    
      int key; //关键字
      TreeNode left; //左节点
      TreeNode right;  //右节点
      TreeNode() {
    
    }
      TreeNode(int val) {
    
     this.val = val; }
      TreeNode(int val, TreeNode left, TreeNode right) {
    
    
          this.val = val;
          this.left = left;
          this.right = right;
      }
  }

3. Las reglas de construcción más básicas del árbol de búsqueda binaria
Para cualquier nodo de nodo, la clave de cada nodo del subárbol izquierdo no puede ser mayor que node.key, y la clave de cada nodo del subárbol derecho no puede ser menor que node.key . Esta regla de construcción puede conducir a una propiedad del árbol de búsqueda binaria: si childNode es un nodo en el subárbol izquierdo del nodo, entonces childNode.key <= node.key, de manera similar, si está en el subárbol derecho, entonces childNode.key> = node.key.

4. Recorrido de búsqueda de árbol binario
(1) Hay dos métodos principales para recorrer el árbol binario, a saber, recorrido de búsqueda de amplitud BFS y recorrido de búsqueda profunda DFS. El núcleo del recorrido de búsqueda de amplitud es la aplicación de la estructura de datos de la cola; el recorrido de búsqueda profunda tiene Hay dos formas, una es atravesar el diseño de la función recursiva y la otra es usar la estructura de datos de la pila para atravesar

1> DFS

//递归遍历
 public void search(TreeNode root){
    
    
        
        if(root==null)
           return;
        search(root.left);
        search(root.right);
    }
  //利用栈进行遍历
  public void search(TreeNode root){
    
    
     public void search(TreeNode root) {
    
    
        TreeNode node = root;
        Stack<TreeNode> DFS = new Stack<>();
        while (!DFS.isEmpty() || node != null) {
    
    
            while (node != null) {
    
    
                DFS.push(node);
                node = node.left;
            }
            node = DFS.pop().right;
        }
    }
 }

2> BFS

 //利用队列进行遍历
 public void search(TreeNode root){
    
    
        TreeNode node=root;
        Queue<TreeNode>DFS=new LinkedList<>();
        DFS.offer(node);
        while(!DFS.isEmpty()||node!=null){
    
    
            node=DFS.poll();
            if(node.left!=null) 
                DFS.offer(node.left);
            if(node.right!=null) 
                DFS.offer(node.right);
        }

}

(2) Algoritmo avanzado de recorrido de árbol binario: algoritmo de Morris. El algoritmo de Morris reduce en gran medida la complejidad espacial de atravesar el árbol de búsqueda binario. El algoritmo utiliza principalmente una gran cantidad de nodos vacíos que deben existir en el árbol de búsqueda binaria (los nodos finales deben tener nodos vacíos), lo que guarda la pila O hacer cola.

Los principales pasos del algoritmo:

1>. Para el nodo hijo del árbol de búsqueda binaria, si el nodo no tiene un hijo izquierdo, visite el hijo derecho del nodo, si el nodo tiene un hijo izquierdo, busque el nodo más a la derecha en el subárbol izquierdo del nodo (es decir, en el subárbol izquierdo del nodo) El último nodo del recorrido de secuencia) se registra como morrisBack.

2>. Según si el hijo derecho de morrisBack está vacío, realice las siguientes operaciones: si el hijo derecho está vacío, apunte su hijo derecho al nodo y luego visite al hijo izquierdo; si el hijo derecho no está vacío, significa que hemos atravesado el nodo Para el subárbol izquierdo, dejamos el hijo derecho de morrisBack vacío (para no destruir la estructura del árbol de búsqueda binaria), y luego visitamos el hijo derecho del nodo (regrese al nodo principal del subárbol o visite el nodo derecho)

3>. Repita las operaciones anteriores hasta que se visite el árbol completo.

Diagrama del algoritmo de Morris:
fuente de imágenes
Inserte la descripción de la imagen aquí

class Solution {
    
    
    public void Search(TreeNode root) {
    
    
        TreeNode node=root;
        TreeNode morrisBack;
        while(node!=null){
    
    
            
            if(node.left!=null){
    
    
                morrisBack=node.left;
               
                while(morrisBack.right!=null&&morrisBack.right!=node)
                    morrisBack=morrisBack.right;
                
                if(morrisBack.right==null){
    
    
                    morrisBack.right=node;
                    node=node.left;
                }
                else{
    
    
                    morrisBack.right=null;
                    node=node.right;
                }
            }
            
            else
                node=node.right;


        }

    }
}

5. Clasificación
transversal del árbol binario El algoritmo transversal del árbol binario tiene tres formas especiales, que son recorrido de preorden, recorrido de orden medio y recorrido posterior.
Para el recorrido de preorden, significa que para el nodo actual, el nodo se visita primero, luego su hijo izquierdo y finalmente su hijo derecho.
Para un recorrido en orden, para el nodo actual, primero visite su hijo izquierdo, luego visite el nodo y finalmente visite su hijo derecho. (Para un árbol de búsqueda binario, se accede al recorrido de orden medio en orden ascendente del valor clave del nodo, y se puede obtener una matriz en orden ascendente del valor clave del nodo).
Para el recorrido posterior, primero es para el nodo actual Visite su hijo izquierdo, luego su hijo derecho y finalmente el nodo.
Inserte la descripción de la imagen aquí
Tome el árbol de búsqueda binaria en la figura anterior como ejemplo:

Recorrido de reserva:

//递归算法
class Solution {
    
    
    public void search(TreeNode root) {
    
    
        if(root ==null)
            return;
        System.out.print(root.val+" ");
        search(root.left);
        search(root.right);
    }
}
//非递归算法
 public void search(TreeNode root) {
    
    
        TreeNode node = root;
        Stack<TreeNode> DFS = new Stack<>();
        while (!DFS.isEmpty() || node != null) {
    
    
            while (node != null) {
    
    
                System.out.print(node.val+" ");
                DFS.push(node);
                node = node.left;
            }
            node = DFS.pop().right;
        }
    }

Resultado de salida: 6 5 2 5 7 9 8

Recorrido en orden:

//递归算法
class Solution {
    
    
    public void search(TreeNode root) {
    
    
        if(root ==null)
            return;
        search(root.left);
        System.out.print(root.val+" ");
        search(root.right);
    }
}
//非递归算法
 public void search(TreeNode root) {
    
    
        TreeNode node = root;
        Stack<TreeNode> DFS = new Stack<>();
        while (!DFS.isEmpty() || node != null) {
    
    
            while (node != null) {
    
    
                DFS.push(node);
                node = node.left;
            }
            node = DFS.pop();
            System.out.print(root.val+" ");
            node=node.right; 
        }
    }

Resultado de salida: 2 5 5 6 7 8 9

Recorrido posterior al pedido:

//递归算法
class Solution {
    
    
    public void search(TreeNode root) {
    
    
        if(root ==null)
            return;
        search(root.left);
        search(root.right);
        System.out.print(root.val+" ");
    }
}
//非递归算法
public void search(TreeNode root) {
    
    
        HashMap<TreeNode,Integer>check=new HashMap<>();
        TreeNode node = root;
        Stack<TreeNode> DFS = new Stack<>();
        while (!DFS.isEmpty() || node != null) {
    
    
            while (node != null) {
    
    
                check.put(node,1);
                DFS.push(node);
                node = node.left;
            }

            node=DFS.peek();
            if(check.get(node)==1){
    
    
                check.put(node,2);
                node=node.right;
            }
            else{
    
    
                DFS.pop();
                System.out.print(node.val+" ");
                node=null; 
            }
        }
    }

Resultado de salida: 2 5 5 8 9 7 6

Supongo que te gusta

Origin blog.csdn.net/CY2333333/article/details/107882185
Recomendado
Clasificación