二叉树删除节点
删除分为四种情况
- 这个节点左右孩子都有
- 这个节点没有左右孩子
- 这个节点只有左孩子
- 这个节点只有右孩子
1.查找节点位置
struct TreeNode *p = NULL;//遍历指针
struct TreeNode *fp = NULL;//记录指针的父节点
p = root;
while(1)//寻找要删除的位置
{
fp = p;//记录指针的父节点
if(p ->data > data)//左边找
{
p = p ->lchild;
}
else if(p ->data < data)//右边找
{
p = p ->rchild;
}
if(p -> data == data)//找到,退出循环
{
break;
}
}
if(!p)//没有找到要删除的节点
{
return root;
}
2.开始判断
- 这个节点左右孩子都有
处理有两种方法,一种是找左边最大,另一种是找右边最小;
if(p -> lchild && p -> rchild)//左右孩子都有
{
struct TreeNode *q = p;
fp = p;
p = p -> rchild;
while(p -> lchild)//找右边最小的
{
fp = p;
p = p -> lchild;
}
q -> data = p -> data;//交换数据
if(fp -> lchild == p)
{
fp ->lchild = p -> rchild;
free(p);
}
else if(fp -> rchild == p)
{
fp -> rchild = p -> rchild;
free(p);
}
return root;
}
- 这个节点左右孩子都没有
if(!p -> lchild && !p -> rchild)//左右孩子都没有
{
if(p == root)//删除节点为根
{
free(root);
return NULL;
}
if(fp -> lchild == p)//在前一个节点的左边
{
fp -> lchild = NULL;
free(p);
}
else if(fp -> rchild ==p)//在前一个节点的右边
{
fp -> rchild = NULL;
free(p);
}
return root;
}
- 这个节点只有左孩子
if(p -> lchild && !p -> rchild)//只有左孩子,没有右孩子
{
if(root == p)//节点为根
{
root = p -> lchild;
p -> lchild = NULL;
free(p);
return root;
}
if(fp -> lchild == p)//在前一个节点的左边
{
fp -> lchild = p -> lchild;
p -> lchild = NULL;
free(p);
}
else if(fp -> rchild == p)//在前一个节点的右边
{
fp -> rchild = p -> lchild;
p -> lchild = NULL;
free(p);
}
return root;
}
- 这个节点只有右孩子
if(!p -> lchild && p -> rchild)//只有右孩子,没有左孩子
{
if(root == p)//节点为根
{
root = p -> rchild;
p -> rchild = NULL;
free(p);
return root;
}
if(fp -> lchild == p)//在前一个节点的左边
{
fp -> lchild = p -> rchild;
p -> rchild = NULL;
free(p);
}
else if(fp -> rchild == p)//在前一个节点的右边
{
fp -> rchild = p -> rchild;
p -> rchild = NULL;
free(p);
}
return root;
}
完整代码
//删除节点
struct TreeNode * DeleteTreeNode(struct TreeNode *root,char data)
{
if(!root)
{
return NULL;
}
struct TreeNode *p = NULL;//遍历指针
struct TreeNode *fp = NULL;//记录指针的父节点
p = root;
while(1)//寻找要删除的位置
{
fp = p;//记录指针的父节点
if(p ->data > data)//左边找
{
p = p ->lchild;
}
else if(p ->data < data)//右边找
{
p = p ->rchild;
}
if(p -> data == data)//找到了,退出循环
{
break;
}
}
if(!p)//没有找到要删除的节点
{
return root;
}
if(p -> lchild && p -> rchild)//左右孩子都有
{
struct TreeNode *q = p;
fp = p;
p = p -> rchild;
while(p -> lchild)//找右边最小的
{
fp = p;
p = p -> lchild;
}
q -> data = p -> data;//交换数据
if(fp -> lchild == p)
{
fp ->lchild = p -> rchild;
free(p);
}
else if(fp -> rchild == p)
{
fp -> rchild = p -> rchild;
free(p);
}
return root;
}
if(!p -> lchild && !p -> rchild)//左右孩子都没有
{
if(p == root)//删除节点为根
{
free(root);
return NULL;
}
if(fp -> lchild == p)
{
fp -> lchild = NULL;
free(p);
}
else if(fp -> rchild ==p)
{
fp -> rchild = NULL;
free(p);
}
return root;
}
if(p -> lchild && !p -> rchild)//只有左孩子,没有右孩子
{
if(root == p)
{
root = p -> lchild;
p -> lchild = NULL;
free(p);
return root;
}
if(fp -> lchild == p)
{
fp -> lchild = p -> lchild;
p -> lchild = NULL;
free(p);
}
else if(fp -> rchild == p)
{
fp -> rchild = p -> lchild;
p -> lchild = NULL;
free(p);
}
return root;
}
if(!p -> lchild && p -> rchild)//只有右孩子,没有左孩子
{
if(root == p)
{
root = p -> rchild;
p -> rchild = NULL;
free(p);
return root;
}
if(fp -> lchild == p)
{
fp -> lchild = p -> rchild;
p -> rchild = NULL;
free(p);
}
else if(fp -> rchild == p)
{
fp -> rchild = p -> rchild;
p -> rchild = NULL;
free(p);
}
return root;
}
}