二叉查找树的删除节点
二叉查找树的一般操作中最复杂的,虽然删除节点对于人们来收很不友好,但是在很多树中应用又非常广泛。
删除节点的一般思想:
1.找到要删除的节点
2.删除节点
3.用后面的节点替补已删除的节点。
在二叉查找树中删除节点要考虑三种情况:
1.该节点是叶节点(没有子节点)
2.该节点有一个叶子节点
3.该节点有两个叶子节点
以上三种情况是越来越复杂。
public boolean delete(int key) {
Node current = root; //要删除的节点
Node parent = root; //要删除节点的父节点
boolean isLeftChild = true; //标志删除节点为左子树还是右子树
//通过while循环找到要删除的节点
while (current.iData != key) {
parent = current;
if (key < current.iData) {
isLeftChild = true;
current = current.leftChild;
} else {
isLeftChild = false;
current = current.RightChild;
}
if (current == null)
return false;//如果整棵树都为空,则退出循环
}
//以上代码为找到节点要删除的节点。
//这样就清空了整棵树。否则就把父节点的leftLChild或者RightChild字段置为空,
//情况一:删除没有子节点的节点
//先检查它是否真的没有子节点,还要检查它是否根节点,如果是根就要把它置为空。
if (current.leftChild == null && current.RightChild == null) {
if (current == root)//如果要删除节点为根节点
root = null;//整棵树都置空
else if (isLeftChild)//要删除节点为左节点
parent.leftChild = null;
else
parent.RightChild = null;//要删除节点为右节点
} //到此没有节点的已经写完
//情况二:删除只有一个节点的情况
else if (current.RightChild == null)//删除节点只有左节点
if (current == root)
root = current.leftChild;
else if (isLeftChild) //左节点,但不是根节点
parent.leftChild = current.leftChild;
else
parent.RightChild = current.leftChild;
else if (current.leftChild == null)//删除节点只有右节点
if (current == root)
root = current.RightChild;
else if (isLeftChild)
parent.leftChild = current.RightChild;
else
parent.RightChild = current.RightChild;
//情况三:删除有两个子节点节点,
//删除有两个子节点的情况,问题关键是删除的节点后,应该用哪一个节点来替补被删除的节点呢?
//答案是:用右子树的最小节点来替补,这就保证了二叉查找树的原本特性
else{
Node successor=getSuccessor(current);
if(current==root)
root=successor;
else if(isLeftChild)
parent.leftChild=successor;
else
parent.RightChild=successor;
successor.leftChild=current.leftChild;
}
return true;
}
//寻找右子树的最小节点
private Node getSuccessor(Node delNode){
Node successorParent=delNode; //delNode是要删除的节点
Node successor=delNode; //successor为记录找到的右子树的最小节点
Node current=delNode.RightChild; //current记录删除节点的右子树
//二叉查找树的特性:最左节点为最小值,最右节点为最大值
//左节点不为空,直走找到右子树的最左节点-->那个就是右子树的最小值
while(current!=null){
successorParent=successor;
successor=current;
current=current.leftChild;
}
//还要判断右子树最小节点是否等于删除节点的右节点
if(successor!=delNode.RightChild){
//如果最小节点不是要删除节点的右孩子,就要处理最小节点的右孩子节点
successorParent.leftChild=successor.RightChild;
successor.RightChild=delNode.RightChild;
}
return successor;
}
下图为删除只有一个节点的情况,左右节点分别删除的情况。
好了,以上为二叉查找树的删除部分内容,动手试试吧!!!