分两种情况
一. 要删除的节点不同时有左右子树
1.叶节点,直接删除
2.只有左枝或只有右枝,可以直接用左子树或右子树代替节点
二. 要删除的节点同时有左右子树
化繁为简
1.先找出该节点的直接后继,因为该节点同时有左右两枝,所以直接后继一定是它的右子树的最小(最左)节点。并且因为直接后继是一个子树中的最小节点,所以直接后继没有左子树。
2.将该节点的值和直接后继的值交换
(1)如果交换发生在树的相邻两层:
1)记下直接后继的父节点p(和被删除节点相等)
2)p的右子树替换为直接后继的右子树(因为直接后继在右子树中且直接后继没有左子树)
(2)如果交换发生在不相邻的两层:
1)记下直接后继的父节点p(和被删除节点不相等)
2)p的左子树替换为直接后继的右子树(因为直接后继在右子树的左子树中且直接后继没有左子树)
java实现:
public boolean remove(T e) {
BinNode<T> x = search(e);
if(x == null) return false; // 找不到被删除节点,返回false
// 删除节点部分
BinNode<T> del = x; // 实际被删除的节点
Binode<T> delPar = x.parent; //被删除节点的父节点
BinNode<T> succ = null; // 被删除节点的代替者
// 只有左子树或只有右子树可以直接用子树代替该节点
if(x.lChild == null) succ = (delPar.rChild = x.rChild);
else if(x.rChild == null) succ = (delPar.rChild = x.lChild);
else { // 左右子树都有时
del = del.succ();
// 要删除节点的和它的直接后继交换
T temp = x.data;
x.data = del.data;
del.data = temp;
BinNode<T> u = del.parent;
if(u.isEqual(x)) { // 交换相邻两层
u.rChild = (succ = del.rChild);
}
else { // 交换不相邻的两层
u.lChild = (succ = del.rChild);
}
}
_hot = del.parent; // _hot记录当前节点的父节点
if(succ != null)
succ.parent = _hot;
_size--; // 节点数减一
updateHeightAbove(_hot); // 更新树高
return true;
}