数据结构--二叉树删除树节点
删除树节点需要考虑以下情况:
删除叶子节点
步骤
- 找到要删除的节点targetNode
- 找到targetNode的父结点parentNode(考虑父节点是否存在)
- 确定targetNode是parentNode的左子树还是右子树
- 根据前面的情况进行删除
- 左子树:parentNode.left=null
- 右子树:parentNode.right=null
删除非叶子节点
有两个节点
步骤
- 找到要删除的节点targetNode
- 找到targetNode的父结点parentNode(考虑父节点是否存在)
- 去找targetNode的右子树的左子树中的最小值(或左子树右子树的最大值)
- 将targetNode的值和最小值的值进行互换
- 即将问题转化为--->删除叶子节点
只有一颗子树
步骤
- 找到要删除的节点targetNode
- 找到targetNode的父结点parentNode(考虑父节点是否存在)
- 确定targetNode是parentNode的左子树还是右子树
- 确定targetNode有的是左子树还是右子树
- 情景1:是左子树,有左子树,将自己的左子树赋给父结点的左子树
- 情景2:是左子树,有右子树,将右子树赋给父节点的左子树
- 情景3:是右子树,有左子树,将自己的左子树赋给父结点的右子树
- 情景4:是右子树,有右子树,将自己的右子树赋给父结点的右子树
有了上述概念后,就可以顺利的编写:
查询删除节点
public TreeNode SearchNode(TreeNode node,int value){
if(node==null){
return null;
}
if(value==node.data){
return node;
}else if(value<node.data){
if(node.left!=null){
return SearchNode(node.left,value);
}
}else{
if(node.right!=null){
return SearchNode(node.right,value);
}
}
return null;
}
查询父结点
public TreeNode SearchParent(TreeNode node,int value){
if(node==null){
return null;
}
if(node.left!=null&&node.left.data==value || node.right!=null&&node.right.data==value){
return node;
}else{
if(node.left!=null&&value<node.data){
return SearchParent(node.left,value);
}else if(node.right!=null&&value>node.data){
return SearchParent(node.right,value);
}else{
return null;
}
}
}
找到最小节点
public int delRightTreeMin(TreeNode node){
TreeNode tempNode = node;
while (tempNode.left !=null){
tempNode = tempNode.left;
}
return tempNode.data; //最值进行返回
}
删除
//删除节点
public void delete(TreeNode node,int value){
if(node==null){
return;
}
//单独的节点
if(node.left==null&&node.right==null){
node=null;
return;
}
//首先查询要删除的节点
TreeNode targetNode=SearchNode(node,value);
if(targetNode==null){
return;
}
TreeNode parentNode=SearchParent(node,value);
if(targetNode.left==null&&targetNode.right==null){//叶子节点
if(parentNode.left!=null&&parentNode.left.data==targetNode.data){
parentNode.left=null;
}else if(parentNode.right!=null&&parentNode.right.data==targetNode.data){
parentNode.right=null;
}
}else if(targetNode.left!=null&&targetNode.right!=null){//双子树
int minValue=delRightTreeMin(targetNode.right);
delete(targetNode.right,minValue);//先删除叶子节点
targetNode.data=minValue;//再覆盖原位置
}else{//单子树
if(targetNode.left!=null){//当前要删除的节点有左子树
if(parentNode.left.data==targetNode.data){//删除的节点是父节点的左子树
parentNode.left=targetNode.left;
}else{//删除的节点是父节点的右子树
parentNode.right=targetNode.left;
}
}else{//当前要删除的节点有右子树
if(parentNode.left.data==targetNode.data){//删除的节点是父节点的左子树
parentNode.left=targetNode.right;
}else{//删除的节点是父节点的右子树
parentNode.right=targetNode.right;
}
}
}
}