Conceptos relacionados de árbol binario y recorrido de secuencia frontal, media y posterior

Árbol binario

Árbol binario: Un árbol binario es una estructura de árbol con un máximo de dos subárboles por nodo; es un conjunto finito de n (n> = 0) nodos. Es un árbol vacío (n = 0) o consta de un nodo raíz. y Consiste en dos árboles binarios disjuntos llamados subárbol izquierdo y subárbol derecho.

img

Árbol binario completo

Árbol binario completo: a excepción de la última capa, el número de nodos en cada capa alcanza el máximo, solo faltan unos pocos nodos a la derecha en la última capa;

img

Árbol binario completo

Árbol binario completo: excepto la última capa, todos los nodos de cada capa tienen dos subnodos; un árbol binario completo es un árbol binario completo especial;

img

Árbol de ordenación binaria (árbol de búsqueda binaria)

El árbol de búsqueda binaria es una especie de árbol binario, y es una especie de árbol binario muy utilizado. También se llama BST en inglés y también se conoce como: árbol de búsqueda binaria y árbol de ordenación binaria.

  • El valor de cualquier nodo es mayor que los valores de todos los nodos en su subárbol izquierdo
  • El valor de cualquier nodo es menor que el valor de todos los nodos en su subárbol derecho
  • Su subárbol izquierdo y derecho también es un árbol de búsqueda binario

Árbol de ordenación binaria (búsqueda): en un árbol binario, cada nodo no es más pequeño que cualquier elemento en su subárbol izquierdo, y no es más grande que cualquier elemento en su subárbol derecho. También se llama árbol de búsqueda binaria.

img

Árbol binario equilibrado

Balanced Binary Tree es una evolución de los árboles de búsqueda binarios y el primer árbol binario en introducir el concepto de equilibrio. En 1962, GM Adelson-Velsky y EM Landis inventaron este árbol, por lo que también se le llama árbol AVL.

Un árbol binario equilibrado requiere que para cada nodo, la diferencia entre la altura de sus subárboles izquierdo y derecho no pueda exceder 1. Si un nodo se inserta o elimina de modo que la diferencia de altura es mayor que 1, es necesario rotar entre los nodos para mantener el árbol binario nuevamente en un estado de equilibrio.

Esta solución es una buena solución al problema del árbol de búsqueda binario que degenera en una lista enlazada, y la complejidad de tiempo de inserción, búsqueda y eliminación se mantiene en O (logN) en el mejor y el peor de los casos. Sin embargo, la rotación frecuente sacrificará aproximadamente el tiempo O (logN) para la inserción y eliminación, pero en relación con el árbol de búsqueda binaria, el tiempo es mucho más estable.

Cruce de árbol binario

package com.michealkz.tree;

import com.michealkz.printer.BinaryTreeInfo;

import java.util.Comparator;
import java.util.LinkedList;
import java.util.Queue;

/**
 * 二叉搜索树继承自BinaryTreeInfo 实现其中的方法以便进行打印
 *
 * @param <E>
 */
public class BinarySearchTree<E> implements BinaryTreeInfo {
    
    
    private int size;
    private Node<E> root;
    private Comparator<E> comparator;

    public int size() {
    
    
        return size;
    }

    public boolean isEmpty() {
    
    
        return size == 0;
    }

    public void clear() {
    
    
        root = null;
        size = 0;
    }

    public void add(E element) {
    
    
        elementNotNullCheck(element);

        // 添加第一个节点
        if (root == null) {
    
    
            root = new Node<E>(element, null);
            size++;
            return;
        }

        // 添加的不是第一个节点 则找到父节点
        Node<E> parent = root;
        Node<E> node = root;
        int cmp = 0;
        do {
    
    
            /*
             * 根据compare的返回值正负或者相等来判断是左子树还是右子树还是相等
             */
            cmp = compare(element, node.element);
            // 将节点保存下来作为查找下一个的父节点
            parent = node;
            if (cmp > 0) {
    
    
                node = node.right;
            } else if (cmp < 0) {
    
    
                node = node.left;
            } else {
    
     // 相等
                node.element = element;
                return;
            }
        } while (node != null);

        // 看看插入到父节点的哪个位置
        Node<E> newNode = new Node<E>(element, parent);
        if (cmp > 0) {
    
    
            parent.right = newNode;
        } else {
    
    
            parent.left = newNode;
        }
        size++;
    }

    /*
     * @return 返回值等于0,代表e1和e2相等;返回值大于0,代表e1大于e2;返回值小于于0,代表e1小于e2
     */
    private int compare(E e1, E e2) {
    
    
        if (comparator != null) {
    
    
            return comparator.compare(e1, e2);
        }
        return ((Comparable<E>) e1).compareTo(e2);
    }

    private void elementNotNullCheck(E element) {
    
    
        if (element == null) {
    
    
            throw new IllegalArgumentException("element must not be null");
        }
    }

    // 二叉树的前序遍历操作
    public void preorderTraversal() {
    
    
        preorderTraversal(root);
    }

    // 二叉树的前序遍历传入根节点进行遍历操作
    private void preorderTraversal(Node<E> node) {
    
    
        if (node == null) return;
        System.out.print(node.element + "\t");
        preorderTraversal(node.left);
        preorderTraversal(node.right);
    }

    // 二叉树中序遍历
    public void middleOrderTraversal() {
    
    
        middleOrderTraversal(root);
    }

    // 二叉树中序遍历实现逻辑
    private void middleOrderTraversal(Node<E> node) {
    
    
        if (node == null) return;
        middleOrderTraversal(node.left);
        System.out.print(node.element + "\t");
        middleOrderTraversal(node.right);
    }

    // 二叉树后序遍历
    public void postOrderTraversal() {
    
    
        postOrderTraversal(root);
    }

    // 二叉树后序遍历实现
    private void postOrderTraversal(Node<E> node) {
    
    
        if (node == null) return;
        postOrderTraversal(node.left);
        postOrderTraversal(node.right);
        System.out.print(node.element + "\t");
    }

    // 二叉树层序遍历
    public void levelOrderTraversal() {
    
    
        levelOrderTraversal(root);
    }

    // 二叉树层序遍历实现逻辑

    /**
     * 二叉树层序遍历很重要
     * 遍历思路:
     *  - 1.定义队列存放节点
     *  - 2.首先将根节点入队列
     *  - 3.如果队列不为空,那么将队列顶部元素出队
     *  - 4.输出根节点的值
     *  - 5.判断根节点左右节点是否为空,如果不为空,那么将左右节点入队列,只要队列不为空就一直执行while循环
     * @param root
     */
    private void levelOrderTraversal(Node<E> root) {
    
    
        Queue<Node<E>> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
    
    
            Node<E> node = queue.poll();
            System.out.print(node.element + "\t");

            if (node.left != null) {
    
    
                queue.offer(node.left);
            }

            if (node.right != null) {
    
    
                queue.offer(node.right);
            }
        }

    }

    /**
     * 下面是打印需要重写的四个方法
     * 根节点
     */
    @Override
    public Object root() {
    
    
        return root;
    }

    // 左树的寻找方式
    @Override
    public Object left(Object node) {
    
    
        return ((Node<E>) node).left;
    }

    // 右树的寻找方式
    @Override
    public Object right(Object node) {
    
    
        return ((Node<E>) node).right;
    }

    // 打印方式
    @Override
    public Object string(Object node) {
    
    
        Node<E> myNode = (Node<E>) node;
        // 获取父节点保存下来并打印
        String parentString = "null";
        if (myNode.parent != null) {
    
    
            parentString = myNode.parent.element.toString();
        }
        return myNode.element;
    }

    public BinarySearchTree() {
    
    
        this(null);
    }

    public BinarySearchTree(Comparator<E> comparator) {
    
    
        this.comparator = comparator;
    }

    /**
     * 二叉树的 Node节点 对象
     */
    public static class Node<E> {
    
    
        E element;
        Node<E> left;
        Node<E> right;
        Node<E> parent;

        public Node(E element, Node<E> parent) {
    
    
            this.element = element;
            this.parent = parent;
        }

        public boolean isLeaf() {
    
    
            return left == null && right == null;
        }

        public boolean hasTwoChildren() {
    
    
            return left != null && right != null;
        }
    }
}

Supongo que te gusta

Origin blog.csdn.net/qq_43081842/article/details/113838089
Recomendado
Clasificación