树定义
public class BinarySearchTree<T extends Comparable<? super T>> {
// 二叉树节点
private static class BinaryNode<T> {
T data;
BinaryNode<T> left, right;
public BinaryNode(T data, BinaryNode<T> left, BinaryNode<T> right) {
this.data = data;
this.left = left;
this.right = right;
}
}
// 树根
private BinaryNode<T> root;
...
}
搜索节点
// 用于表示搜索结果(作为内部类)
private static class SearchResult<T> {
BinaryNode<T> target; // 目标节点
BinaryNode<T> parent; // 目标节点之父
// getter & setter ...
}
// 查找关键码 e:返回目标节点及其父节点(插入、删除时有用)
public SearchResult<T> search(T e) {
SearchResult<T> result = new SearchResult<>();
BinaryNode<T> current = root, parent = null;
while (current != null) {
int compareResult = e.compareTo(current.data);
// 找到了
if (compareResult == 0) {
break;
}
// 记录父节点,然后:比当前节点小->往左;否则->往右
parent = current;
current = compareResult < 0 ? current.left : current.right;
}
result.target = current;
result.parent = parent;
return result;
}
插入节点
public void insert(T e) {
// 先确定目标节点是否存在
SearchResult<T> result = search(e);
// 已存在
if (result.target != null) {
return;
}
// 插入节点
BinaryNode<T> node = new BinaryNode<>(e, null, null);
// 建立父节点到新插入节点的连接
BinaryNode<T> parent = result.parent;
if (parent == null) { // 为树根
root = node;
} else { // 不是树根
if (e.compareTo(parent.data) < 0) {
parent.left = node;
} else {
parent.right = node;
}
}
}
删除节点
设待删除节点为 v,v 之父为 p,则根据 v 拥有的非空孩子数,可分为两种情况:
(1) v 拥有一个非空孩子
设该非空孩子为 c,则让 c 接替 v,成为 p 的孩子。
(2)v 拥有两个非空孩子
设 rc 为 v 的右孩子,在以 rc 为根的子树中,找到关键码最小的节点,设为 t 。
然后将 v 的关键码设为 t 的关键码(即存放的数据)。因为 t 的关键码是子树 rc 中最小的关键码,所以,更新之后,节点 v 的关键码依然小于等于子树 rc 中的任一节点的关键码,大于左子树中任一节点的关键码,即符合搜索树的限定条件。
最后,删除节点 t 。此时,可以确保节点 t 绝对没有非空左孩子。(如果有的话,则其左孩子的关键码比 t 的还要小,即 t 就不是关键码最小的节点)
即,情况(2)转换为了情况(1)。
// 找到 root 子树中关键码最小的节点及其父节点
private SearchResult<T> findMinimum(BinaryNode<T> root) {
SearchResult<T> result = new SearchResult<>();
BinaryNode<T> parent = null;
// 一直往左即可找到最小者
if (root != null) {
while (root.left != null) {
parent = root;
root = root.left;
}
}
result.target = root;
result.parent = parent;
return result;
}
// 删除
public void remove(T e) {
// 先确认目标节点是否存在
SearchResult<T> result = search(e);
// 不存在
if (result.target == null) {
return;
}
BinaryNode<T> target = result.target; // 待删除节点
BinaryNode<T> parent = result.parent; // 待删除节点之父
// 待删除节点有左右两个非空孩子
// 以待删除节点为根,找到其右子树中关键码最小的节点,让它代替受死
if (target.left != null && target.right != null) {
SearchResult<T> result1 = findMinimum(target.right);
target.data = result1.target.data;
target = result1.target; // 真正被删除的节点
parent = result1.parent;
}
// 现在,待删除节点最多只有一个非空孩子
// 让该孩子节点继承父节点的位置
BinaryNode<T> child = target.left != null ? target.left : target.right;
if (parent != null) { // 待删除节点不是树根
if (parent.left == target) {
parent.left = child;
} else {
parent.right = child;
}
} else { // 待删除节点是树根
root = child;
}
}