嘤嘤嘤,今天补回昨天没有写的博客。
二叉排序树的删除操作比较简单,但是思想很全面,因此本人就写一篇博客纪念一下。
思想:四种类型也可以是三种
1,删除结点p的度为2,即有左右子树。
此时有两种方法,第一种将结点的左子树在中根遍历下的最后一个结点放到p的位置。第二种是将p结点的右子树在中根遍历下的第一个结点放到p的位置。这里本人根据之前的博客二叉树的中根遍历就用了第二种方法。有first()方法,嘤嘤嘤。
2,单只树的根结点,且为叶子结点,度为1。
此时就需要将p的左子树或右子树(只有一个)替换p。so easy.
3,删除结点p是度为1的叶子结点,有父母,是左孩子。
此时需要将p的左孩子或者右孩子替换掉p。用p的孩子替换掉p。相信大家都会,类似于链表的插入。
4,删除结点p是度为1的叶子结点,有父母,是右孩子。
此时需要将p的左孩子或者右孩子替换掉p。用p的孩子替换掉p。相信大家都会,类似于链表的插入。
上代码:
public T remove(T key) {
TriNode<T> p = this.searchNode(key); // 查找关键字为key元素,若查找成功,返回结点,否则返回null
if (p != null && p.left != null && p.right != null) // 找到待删除结点p,若p是2度结点
{
TriNode<T> insucc = this.first(p.right); // 寻找p在中根次序下的后继结点insucc
T temp = p.data; // 交换待删除元素,作为返回值
p.data = insucc.data; // 以后继结点值替换p结点值
insucc.data = temp;
p = insucc; // 转化为删除insucc,删除1、0度结点
}
if (p != null && p == this.root) // p是1度或叶子结点,删除根结点,p.parent==null
{
if (this.root.left != null)
this.root = p.left; // 以p的左孩子顶替作为新的根结点
else
this.root = p.right; // 以p的右孩子顶替作为新的根结点
if (this.root != null)
this.root.parent = null;
return p.data; // 返回被删除根结点元素
}
if (p != null && p == p.parent.left) // p是1度或叶子结点,p是父母的左孩子
if (p.left != null) {
p.parent.left = p.left; // 以p的左孩子顶替
p.left.parent = p.parent; // p的左孩子的parent域指向p的父母
} else {
p.parent.left = p.right; // 以p的右孩子顶替
if (p.right != null)
p.right.parent = p.parent;
}
if (p != null && p == p.parent.right) // p是1度或叶子结点,p是父母的右孩子
if (p.left != null) {
p.parent.right = p.left; // 以p的左孩子顶替
p.left.parent = p.parent;
} else {
p.parent.right = p.right; // 以p的右孩子顶替
if (p.right != null)
p.right.parent = p.parent;
}
return p != null ? p.data : null;
}