二叉排序树是有序的,删除某个结点后,要保证依然有序,这是指导原则。
二叉排序树的删除,可分为三种情况:被删除结点无子结点,被删除结点有一个子树(结点),被删除结点有两个子树(结点)。前两种情况网上已有很多讨论,这里不再赘述。主要讲一下第三种情况,即,被删除结点有两个子结点。
假设p是被删除结点,父结点是q,有两个左右子结点x,y,则p有可能是根结点(此时忽略q),也有可能位于根结点的左子树或右子树上。当p是根结点时,中序访问顺序是xpy,则删除p后,中序访问顺序应该是xy,按中序遍历规则,可反推出x应变为根结点,y应该是x的右子树。当p是根的左子树中的某个结点时,中序访问顺序是xpyq,删除p后,访问顺序应该是xyq,同样反推,可知,y是x的右子树,q是x的父结点。当p是根的右子树中的某个结点时,中序访问顺序是qxpy,删除p后,访问顺序应该是qxy,同样反推,可知,q是x的父结点,y是x的右子树。
当我们综合分析这三种情况时,规律出现了!无论哪种情况,删除p后,q都是x的父结点,y都是x的右子结点,即p被删除后,p被p的左子结点x代替,p的右子结点成为x的右子结点。根据这一思路,用java代码简单实现二叉排序树的删除算法如下:
public boolean deleteNode(BTNode btn, int key)
{
if (btn == null)
return false;
else if (btn.getData() == key)
Delete(btn);
else if (btn.getData() < key)
deleteNode(btn.getRight(), key);
else
deleteNode(btn.getLeft(), key);
return true;
}
protected boolean Delete(BTNode btn)
{
if (btn.getLeft() == null)
{
btn.setNode(btn.getRight());
} else if (btn.getRight() == null)
{
btn.setNode(btn.getLeft());
} else
{
BTNode t = null, lt = btn.getLeft(), rt = btn.getRight();
while (lt != null)
{
t = lt;// lt的父类
lt = lt.getRight();
}
t.setRight(rt);
btn.setNode(btn.getLeft());
}
return true;
}
BTNode类是树的结点的封装。BTNode类的setNode()方法实现对BTNode对象的赋值。
本文为原创,转载请注明出处。