Árbol de búsqueda binaria, Set y Map (JAVA)

árbol de búsqueda binaria

El árbol de búsqueda binaria, también llamado árbol de clasificación binaria , es un árbol binario o árbol vacío con las siguientes propiedades :

  1. Si su subárbol izquierdo no está vacío, los valores de todos los nodos en el subárbol izquierdo son menores que el valor del nodo raíz.
  2. Si su subárbol derecho no está vacío, los valores de todos los nodos en el subárbol derecho son mayores que el valor del nodo raíz.
  3. Cada uno de sus subárboles es también un árbol de búsqueda binario.

La inserción en un árbol de búsqueda binario es muy sencilla:

  1. Inicie la comparación desde el nodo raíz, si es mayor que el nodo raíz, atraviese el subárbol derecho, si es menor que el nodo raíz, atraviese el subárbol izquierdo.
  2. Realice las operaciones anteriores en todos los subárboles.
  3. Hasta que se atraviese un nodo vacío, inserte el elemento que se insertará en este nodo vacío.
public class BinarySearchTree {

    public static class TreeNode {
        public int key;
        public TreeNode left;
        public TreeNode right;

        TreeNode(int key) {
            this.key = key;
        }
    }

    public TreeNode root;
    /**
     * 插入一个元素
     */
    public boolean insert(int key) {
        TreeNode tmp = new TreeNode(key);
        if (this.root == null) {
            this.root = tmp;
            return true;
        }
        TreeNode privat = this.root;
        TreeNode p1 = this.root;
        while (p1 != null) {
            privat = p1;
            if (p1.key > key) {
                p1 = p1.left;
            }else {
                p1 = p1.right;
            }
        }
        if (privat.key > key) {
            privat.left = tmp;
        }else {
            privat.right = tmp;
        }
        return true;
    }
}

Buscando en un árbol de búsqueda binario:

  1. Inicie la comparación desde el nodo raíz, si es mayor que el nodo raíz, atraviese el subárbol derecho, si es menor que el nodo raíz, atraviese el subárbol izquierdo.
  2. Realice las operaciones anteriores en todos los subárboles.
    //查找key是否存在
    public TreeNode search(int key) {
        if (this.root == null){
            return null;
        }
        TreeNode tmp = this.root;
        while (tmp != null) {
            if (tmp.key > key) {
                tmp = tmp.left;
            }else if (tmp.key < key) {
                tmp = tmp.right;
            }else {
                return tmp;
            }
        }
        return null;
    }

Eliminar un árbol de búsqueda binario es más complicado porque es necesario asegurarse de que el árbol eliminado siga siendo un árbol de búsqueda binario.

Eliminación del árbol de búsqueda binario:

Hay dos situaciones:

  • El árbol izquierdo o derecho está vacío.
  1. Cuando el árbol izquierdo del nodo que se va a eliminar esté vacío , haga que los padres del nodo que se va a eliminar apunten a su subárbol derecho.
  2. Cuando el árbol derecho del nodo que se va a eliminar está vacío , haga que el padre del nodo que se va a eliminar apunte a su subárbol izquierdo.

  • Ni el subárbol izquierdo ni el derecho están vacíos
  1. Encuentre el nodo más a la izquierda (derecha) del subárbol derecho (izquierdo)
  2. Intercambiar los valores de dos nodos.
  3. Eliminar el nodo

    //删除key的值
    public boolean remove(int key) {
        if (this.root == null) {
            return false;
        }
        TreeNode tmp = this.root;
        TreeNode privat = tmp;
        while (tmp != null) {
            if (tmp.key > key) {
                privat = tmp;
                tmp = tmp.left;
            }else if (tmp.key < key) {
                privat = tmp;
                tmp = tmp.right;
            }else {
                break;
            }
        }
        if (tmp == null) {
            return false;
        }
        //左树或者右树为空
        if (tmp.left == null || tmp.right == null) {

            if (tmp.left == null) {
                if (tmp == this.root) {
                    this.root = tmp.right;
                }else {
                    if (privat.left == tmp) {
                        privat.left = tmp.right;
                    }else {
                        privat.right = tmp.right;
                    }
                }

            }else {
           
                if (tmp == this.root) {
                    this.root = tmp.left;
                }else {
                    if (privat.left == tmp) {
                        privat.left = tmp.left;
                    }else {
                        privat.right = tmp.left;
                    }
                }
            }
        }else {
        //左右子树都不为空
            TreeNode a = tmp.right;
            while(a.left != null) {
                privat = a;
                a = a.left;
            }
            tmp.key = a.key;
            if (privat.left == a) {
                privat.left = a.right;
            }else {
                privat.right = a.right;
            }
        }
        return true;
    }

Establecer y mapear

Map y set son contenedores o estructuras de datos especialmente utilizados para la búsqueda , y su eficiencia de búsqueda está relacionada con sus subclases instanciadas específicas .
Generalmente, los datos buscados se denominan palabra clave (Clave) y los datos correspondientes a la palabra clave se denominan valor (Valor) , que se denomina par clave-valor.


Hay dos modelos:

  • Modelo de clave pura:

             Hay un diccionario de inglés para buscar rápidamente si una palabra está en el diccionario y buscar rápidamente si un nombre está en la libreta de direcciones.

  • Modelo clave-valor:

             Cuente el número de veces que aparece cada palabra en el archivo, el resultado estadístico es que cada palabra tiene un número de veces correspondiente: <palabra, número de veces que aparece una palabra> .

Mapa.Entrada

Map.Entry<K, V> es una clase interna implementada dentro de Map para almacenar la relación de mapeo del par clave-valor <key, value>.
Hay varios métodos en ella:

método explicar
K obtener clave() Devolver la llave en la entrada
V obtenerValor() Devuelve el valor en la entrada
V setValue (valor V) Reemplace el valor en el par clave-valor con el valor especificado

Mapa

  • Map es una interfaz y no puede crear instancias de objetos directamente. Si desea crear una instancia de un objeto, solo puede crear una instancia de su clase de implementación TreeMap o HashMap.
  • La clave que almacena pares clave-valor en el mapa es única y el valor se puede repetir.
  • Al insertar un par clave-valor en un TreeMap, la clave no puede estar vacía ; de lo contrario, se generará una excepción NullPointerException y el valor puede estar vacío . Pero tanto la clave como el valor de HashMap pueden estar vacíos .
  • Todas las claves del mapa se pueden separar y almacenar en Establecer para acceder (porque la clave no se puede repetir).
  • Todos los valores del Mapa se pueden separar y almacenar en cualquier subcolección (los valores se pueden duplicar).
  • La clave del par clave-valor en el Mapa no se puede modificar directamente , pero se puede modificar el valor . Si desea modificar la clave, solo puede eliminar la clave primero y luego volver a insertarla.
     
    public static void main(String[] args) {
        Map<Integer,Integer> map = new HashMap<>();
        Map<Integer,Integer> map1 = new TreeMap<>();
    }
Estructura subyacente del mapa ÁrbolMapa HashMap
estructura subyacente árbol negro rojo cubo de hachís

Complejidad del tiempo de inserción/eliminación/búsqueda
O(\log_{2}N) O(1)
¿Está en orden? Acerca del pedido de claves trastorno
Seguridad del hilo no es seguro no es seguro
Insertar/eliminar/buscar diferencias Se requiere comparación de elementos Calcular la dirección hash mediante la función hash
Comparar y sobrescribir La clave debe ser comparable; de ​​lo contrario, se generará
una excepción ClassCastException.
Los tipos personalizados deben anular los
métodos iguales y hashCode
Escenarios de aplicación En escenarios donde se requiere pedido de claves No importa si la clave está en orden o no, se requiere un mayor
rendimiento en el tiempo .

método explicar
V get (clave de objeto) Devuelve el valor correspondiente a la clave
V getOrDefault(Clave de objeto, V defaultValue) Devuelve el valor correspondiente a la clave. Si la clave no existe, se devuelve el valor predeterminado.
V put (tecla K, valor V) Establecer el valor correspondiente a la clave.
V eliminar (clave de objeto) Eliminar la relación de mapeo correspondiente a la clave.
Establecer clave<K>Conjunto() Devuelve un conjunto único de todas las claves.
Colección<V> valores() Devuelve una colección repetible de todos los valores.
Establecer<Map.Entrada<K, V>> entradaConjunto() Devolver todas las relaciones de mapeo clave-valor
booleano contiene clave (clave de objeto) Determinar si la clave está incluida
booleano contieneValor(Valor del objeto) Determinar si el valor está incluido

Colocar

  • Set es una clase de interfaz heredada de Collection
  • Solo la clave se almacena en Set y la clave debe ser única
  • La capa inferior de TreeSet se implementa usando Map , que usa un objeto predeterminado de clave y Objeto como un par clave-valor para insertarse en el Mapa.
  • La función más importante de Set es deduplicar los elementos del conjunto.
  • Las clases comúnmente utilizadas que implementan la interfaz Set incluyen TreeSet y HashSet , y también existe un LinkedHashSet. LinkedHashSet mantiene una lista doblemente vinculada basada en HashSet para registrar el orden de inserción de los elementos.
  • La Clave del Conjunto no se puede modificar, si desea modificarla elimine primero la original y luego vuelva a insertarla.
  • Las claves nulas no se pueden insertar en TreeSet, pero se pueden insertar en HashSet .
Establecer estructura subyacente Conjunto de árboles Conjunto de hash
estructura subyacente árbol negro rojo cubo de hachís

Complejidad del tiempo de inserción/eliminación/búsqueda
O(\log_{2}N) O(1)
¿Está en orden? clave en orden No necesariamente en orden
Seguridad del hilo no es seguro no es seguro
Insertar/eliminar/buscar diferencias Insertar y eliminar según las características del árbol rojo-negro.

1. Primero calcule la dirección hash clave

2. Luego insertar y eliminar

Comparar y sobrescribir La clave debe ser comparable ; de ​​lo contrario, se generará
una excepción ClassCastException.
Los tipos personalizados deben anular los métodos iguales y
hashCode
Escenarios de aplicación En escenarios donde se requiere pedido de claves No importa si la clave está en orden o no, se requiere un mayor
rendimiento en el tiempo .

Supongo que te gusta

Origin blog.csdn.net/2302_76339343/article/details/133500003
Recomendado
Clasificación