
二叉搜索树又称二叉排序树,是一种具有如下性质的二叉树:
注意:二叉搜索树不能有重复的元素

如果对二叉搜索树进行中序遍历,所得到的就是一组有序的升序数据。
对上图的二叉搜索树中序遍历所得结果:0123456789。
它的代码结构:
public static class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode (int val) {
this.val = val;
}
}遍历二叉树,遍历每一个结点(cur)的时候,与所要查找数据(val)进行比较:
图示如下



// 查找
public TreeNode search (int val) {
TreeNode cur = root;
while (cur != null) {
if (cur.val < val) {
// 往右子树查找
cur = cur.right;
} else if (cur.val > val) {
// 往左子树查找
cur = cur.left;
} else {
return cur;
}
}
return null;
}先 遍历查找 搜索树,我们使用双指针来操作:

当 cur 为空时,prev刚好到达最后一个结点,此时可以开始插入新元素了。
插入之前要判断一下 prev的val 和 要插入元素val 的大小关系:

那问题来了,prev 是怎么移动的呢?
很简单:
// 插入
public void insert (int val) {
TreeNode node = new TreeNode(val);
if (root == null) {
root = node;
return;
}
TreeNode prev = null;
TreeNode cur = root;
// 遍历搜索树
while (cur != null) {
if (cur.val < val) {
// 插入右子树
prev = cur;
cur = cur.right;
} else if (cur.val > val) {
// 插入左子树
prev = cur;
cur = cur.left;
} else {
// 二叉搜索树不可以插入两个相同的元素
return;
}
}
// 当cur为空时,就可以插入node了
if (prev.val < val) {
prev.right = node;
} else {
prev.left = node;
}
}首先要找到要被删除的结点,然后删除结点。
删除结点的时候,有三种情况:
1. cur 的左树为空且右树不为空时,我们需要判断 cur 是树根节点还是 prev 的左/右子树:
若 cur 是根结点,就让 cur 等于 cur.right;

若 cur 是 prev 的左树,就把 cur.right 给 prev.left;

若 cur 是 prev 的右树,就把 cur.right 给 prev.right;

2. cur 的右树为空且左树不为空时,我们同样需要判断 cur 是树根节点还是 prev 的左/右子树:
若 cur 是根结点,就让 cur 等于 cur.left;

若 cur 是 prev 的左树,就把 cur.left 给 prev.left;

若 cur 是 prev 的右树,就把 cur.left 给 prev.right;

3. cur 的左右树都不为空时,我们采用 替换删除 的策略:
从 cur 的左树找最右边的结点 / 右树找最左边的结点 (我们称之为 target,其上一个节点为 targetPrev)来替换 cur.val

然后我们需要判断:target 是 targetPrev 的左树还是右树:
若 target 是 targetPrev 的左树,就把 target.right 给 targetPrev.left;

若 target 是 targetPrev 的右树,就把 target.right 给 targetPrev.right;

如此一来,便完成了二叉搜索树的删除操作。
// 删除
public void remove (int val) {
// 找到要删除的结点
TreeNode prev = null;
TreeNode cur = root;
while (cur != null) {
if (cur.val < val) {
prev = cur;
cur = cur.right;
} else if (cur.val > val) {
prev = cur;
cur = cur.left;
} else {
// 找到了,执行删除操作
removeNode(prev,cur);
return;
}
}
}
private void removeNode(TreeNode prev, TreeNode cur) {
if (cur.left == null) { // cur的左子树为空、右子树不为空
if (cur == prev.left) { // cur是prev的左子树
prev.left = cur.right;
} else if (cur == prev.right) { // cur是prev的右子树
prev.right = cur.right;
} else { // cur是根节点
root = cur.right;
}
} else if (cur.right == null) { // cur的右子树为空、左子树不为空
if (cur == parent.left) { // cur是prev的左子树
prev.left = cur.left;
} else if (cur == prev.right) { // cur是prev的右子树
prev.right = cur.left;
} else { // cur是根节点
root = cur.left;
}
} else { // cur的左右子树都不为空
// 替换删除
TreeNode targetPrev = cur;
TreeNode target = cur.right;
// 找到右子树最左边的结点
while (target.left != null) {
targetPrev = target;
target = target.left;
}
// 替换
cur.val = target.val;
// 删除
if (target == targetPrev.left) {
targetPrev.left = target.right;
} else {
targetPrev.right = target.right;
}
}
}完