Buenas tardes, lectores y amigos, el blog anterior introdujo la tabla de símbolos basada en listas enlazadas desordenadas y matrices ordenadas, y presentó las limitaciones de la dicotomía utilizada en este blog. Un nuevo algoritmo que conserva las ventajas del algoritmo anterior: la tabla de símbolos implementada por el árbol de búsqueda binario
Los ejemplos de código para este blog son de: Algorithm Algorithm Forth Edition
[US] Robert Sedgewick Kevin Wayne por Xie Luyun
package com.cmh.algorithm;
import edu.princeton.cs.algs4.Queue;
/**
* @author:起舞的日子
* @date: 2020/4/7 上午12:30
* 二叉查找树实现符号表
*/
public class BST<Key extends Comparable<Key>, Value> {
private Node root;//根结点
private class Node {
/**
* 键
*/
private Key key;
/**
* 值
*/
private Value val;
/**
* 左右节点
*/
private Node left, right;
/**
* 以该节点为根的子树中的结点总数
*/
private int N;
public Node(Key key, Value val, int N) {
this.key = key;
this.val = val;
this.N = N;
}
}
private int size(Node x) {
if (x == null) {
return 0;
} else {
return x.N;
}
}
public int size() {
return size(root);
}
public Value get(Key key) {
return get(root, key);
}
private Value get(Node x, Key key) {
//在以x为根结点的子树中查找并返回key所对应的值,如果找不到返回null
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp < 0) {
return get(x.left, key);
} else if (cmp > 0) {
return get(x.right, key);
} else {
return x.val;
}
}
private Node put(Node x, Key key, Value val) {
//如果key存在于以x为根结点的子树中则更新它的值;否则将以key和val为键值对的新节点插入该子树
if (x == null) {
return new Node(key, val, 1);
}
int cmp = key.compareTo(x.key);
if (cmp < 0) {
x.left = put(x.left, key, val);
} else if (cmp > 0) {
x.right = put(x.right, key, val);
} else {
x.val = val;
}
x.N = size(x.left) + size(x.right) + 1;
return x;
}
/**
* max()
* min()
* floor()
* ceiling()
*/
public Key min() {
return min(root).key;
}
private Node min(Node x) {
if (x.left == null) {
return x;
}
return min(x.left);
}
public Key floor(Key key) {
Node x = floor(root, key);
if (x == null) {
return null;
}
return x.key;
}
private Node floor(Node x, Key key) {
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp == 0) {
return x;
}
if (cmp < 0) {
return floor(x.left, key);
}
Node t = floor(x.right, key);
if (t != null) {
return t;
} else {
return x;
}
}
/**
* 排名
*/
public Key select(int k) {
return select(root, k).key;
}
private Node select(Node x, int k) {
//返回排名为k的节点
if (x == null) {
return null;
}
int t = size(x.left);
if (t > k) {
return select(x.left, k);
} else if (t < k) {
return select(x.right, k - t - 1);
} else {
return x;
}
}
public int rank(Key key) {
return rank(key, root);
}
private int rank(Key key, Node x) {
//返回以x为根结点的子树中小于x.key的键的数量
if (x == null) {
return 0;
}
int cmp = key.compareTo(x.key);
if (cmp < 0) {
return rank(key, x.left);
} else if (cmp > 0) {
return 1 + size(x.left) + rank(key, x.right);
} else {
return size(x.left);
}
}
/**
* 删除
*/
public void deleteMin() {
root = deleteMin(root);
}
private Node deleteMin(Node x) {
if (x.left == null) {
return x.right;
}
x.left = deleteMin(x.left);
x.N = size(x.left) + size(x.right) + 1;
return x;
}
public void delete(Key key) {
root = delete(root, key);
}
/**
* 即时删除
*/
private Node delete(Node x, Key key) {
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp < 0) {
x.left = delete(x.left, key);
} else if (cmp > 0) {
x.right = delete(x.right, key);
} else {
if (x.right == null) {
return x.left;
}
if (x.left == null) {
return x.right;
}
Node t = x;
x = min(t.right);
x.right = deleteMin(t.right);
x.left = t.left;
}
x.N = size(x.left) + size(x.right) + 1;
return x;
}
/**
* 二叉查找树的范围查找操作
* 中序遍历
*/
private void keys(Node x, Queue<Key> queue, Key lo, Key hi) {
if (x == null) {
return;
}
int cmplo = lo.compareTo(x.key);
int cmphi = hi.compareTo(x.key);
if (cmplo < 0) {
keys(x.left, queue, lo, hi);
}
if (cmplo <= 0 && cmphi >= 0) {
queue.enqueue(x.key);
}
if (cmphi > 0) {
keys(x.right, queue, lo, hi);
}
}
}
Resumen:
/ **
* 1. No es fácil de entender
* 2. Si el usuario inserta todas las claves en la tabla de símbolos en orden o en orden inverso, puede ocurrir el peor de los casos: puede haber N nodos en la ruta de búsqueda.
* Entonces, hay mejores algoritmos y estructuras de datos, solo guárdelo para el próximo estudio
* /