二叉树删除节点比较麻烦,一般可能会设置一个isdeleted标记删除的节点而不真的删除节点,删除情况有以下几种:
1,删除的节点是根节点
2,删除的节点无子节点
3,删除的节点只有一个子节点
4,删除的节点有2个子节点。这里面又要判断删除的节点的右子节点有无左子节点,如无,将右子节点替换删除的节点即可;如有,找到最左子节点,去替换要删除的节点,还要注意最左子节点可能也有右子节点,这个节点也要接到最左子节点的父节点上去
以下是代码:
//删除根节点代码有误,在其他判断里加上一个判断是否是根的条件即可
boolean delete(int key){
if(!isEmpty()){
Node current=root;
Node temp=root;
while(current.data!=key){
temp=current;//保存要删除节点的父节点
if(key<current.data)
current=current.left;
else current=current.right;
if(current==null)
return false;
}
if(current==root)//根节点,有误,在其他处判断
root=null;
else if(current.left==null&¤t.right==null){//无子节点
if(current.data<temp.data)
temp.left=null;
else temp.right=null;
}
else if(current.left==null&¤t.right!=null){//右子节点
if(current.data<temp.data)
temp.left=current.right;
else temp.right=current.right;
}
else if(current.left!=null&¤t.right==null){//左子节点
if(current.data<temp.data)
temp.left=current.left;
else temp.right=current.left;
}
else{//有2个子节点
if(current.right.left==null){//要删除的节点的右子节点没有左子节点
current.right.left=current.left;
if(current.data<temp.data){
temp.left=current.right;
}
else{
temp.right=current.right;
}
}
else{
Node t=current.right.left;
Node temp1=current.right;
while(t.left!=null){
t=t.left;
temp1=temp1.left;//保留要删除节点的右子节点的最左子节点的父节点
}
if(t.right==null){//此时t肯定无左子节点
t.left=current.left;
t.right=current.right;
if(current.data<temp.data){
temp.left=t;
}
else{
temp.right=t;
}
temp1.left=null;
}
else{
Node temp2=t.right;
t.left=current.left;
t.right=current.right;
if(current.data<temp.data)
temp.left=t;
else temp.right=t;
temp1.left=temp2;
}
}
}
return true;
}
else return false;
}
这里面(可能会)存在一个问题,是一个顺序问题,比如你如果先把最左子节点接到要删除的节点的父节点上去,然后再把要删除节点的左子节点接到替换后的最左子节点上去,以及之后的一些接上节点操作,要删除节点的父节点一旦不再指向它,那么它的和它的子节点可能当垃圾回收掉,虽然引用不指向它只有片刻时间,我也不知道是不是存在被回收的可能性,但是最好顺序要做好。代码中顺序应该是没有逻辑问题的。