一、简单介绍。
1、二分搜索树的删除操作,其实并不简单,我们需要找到我们要删除的元素。然后分情况考虑。
第一种,没有左孩子,我们直接获取一个节点,保持其右孩子,然后进行让要删除的节点的右孩子至于空,然后返回其右孩子。
第二种,没有右孩子,我们直接获取一个节点,保存其左孩子,然后进行让要删除节点的左孩子至于空,然后返回其左孩子。
第三种,左右孩子都为空,我们直接返回空。
第四种,如果左右孩子都不为空,我们获取该节点的前驱节点或者后继节点,来替换它的位置。
2、在删除某个节点之前,我们先来讨论下一些特使情况的处理。
第一种,删除最小节点。我们可以获取的是左子树最左的节点。
第二种,删除最大节点。我们可以获取的是右子树左右边的节点。
二、代码实现
1、获取最小元素
/**
* 寻找二分搜索树的最小元素
*/
public T minimum() {
if (size == 0) {
throw new IllegalArgumentException("该树的没有节点");
}
Node node = minimum(root);
return node.e;
}
/**
* 寻找二分搜索树的最小元素。
*
* @param node
* @return
*/
private Node minimum(Node node) {
if (node.left == null) {
return node;
}
return minimum(node.left);
}
2、获取最大元素
/**
* 寻找二分搜索树的最大元素
*/
public T maximum() {
if (size == 0) {
throw new IllegalArgumentException("该树的没有节点");
}
return maximum(root).e;
}
private Node maximum(Node node) {
if (node.right == null) {
return node;
}
return maximum(node.right);
}
3、删除最小元素
/**
* 移除二分搜索树中的元素
* 从二分搜索树中删除最小值所在节点, 返回最小值
*/
public T removeMin() {
T res = minimum();
root = removeMin(root);
return res;
}
/**
* 删除最小节点并返回删除后的树的根节点
*
* @param node
* @return
*/
private Node removeMin(Node node) {
if (node.left == null) { //表示要删除的是该节点。
Node nodeRight = node.right;
node.right = null;
size--;
return nodeRight;
}
node.left = removeMin(node.left); //如果不是,就继续向左找。
return node;
}
4、删除最大元素
/**
* 删除最大元素
*
* @return
*/
public T removeMax() {
T res = maximum();
root = removeMax(root);
return res;
}
/**
* 删除当前子树的最大节点,并返回根节点、
*
* @param node
* @return
*/
private Node removeMax(Node node) {
if (node.right == null) { //表示的是找到了最大元素
Node leftNode = node.left;
node.left = null;
size--;
return leftNode;
}
node.right = removeMax(node.right); //没有找到就去右子树继续找。
return node;
}
5、删除指定的元素
/**
* 删除指定的元素
*
* @param t
*/
public void remove(T t) {
root = remove(root, t);
}
/**
* 删除指定的元素,并返回删除节点后,返回新树的根节点。
*
* @param node
* @param t
* @return
*/
private Node remove(Node node, T t) {
if (node == null) { //如果删除的节点不存在就返回空节点。表示删除的节点不存在。
return null;
}
if (node.e.compareTo(t) > 0) { //表示的是要删除的节点小
root.left = remove(node.left, t);
} else if (node.e.compareTo(t) < 0) {//表示的是要删除的节点大
node.right = remove(node.right, t);
} else {
if (node.left == null) { //如果删除的节点的左节点为null
Node nodeRight = node.right; //获取右边节点
node.right = null;
size--;
return nodeRight;
}
if (node.right == null) { //如果被删除的元素右节点为Null
Node nodeLeft = node.left;
node.left = null;
size--;
return nodeLeft;
}
//最后一个情况就是左右元素都不为null;
//1、找出右边的最小节点 后继节点
Node successor = minimum(node.right);
successor.left = node.left;
successor.right = removeMin(node.right); //删除右边节点的最小节点
node.left = node.right = null;
size--;
return successor;
}
}
三、总结
二分搜索树的知识基本已经结束完,我们学习二分搜索树,我们主要是学了二分搜索树咋样插入一个元素,咋样查找一个元素,咋样去删除一个元素。咋样便利二分搜索树,分为前序中序后序便利。分别用递归和非 递归实现。然后讲解了,二分搜索树的层次便利。利用队列实现。