删除二叉搜索树节点的三种情景:
情景1:删除的节点没有子树
如图,删除元素10,我们只需要将它的父节点9的右指针指向NULL,释放元素10的节点;
代码:
if (root->left == NULL && root->right == NULL) //节点没有左节点和右节点
{
free(root); //释放内存
root = NULL;
}
情景2:删除的节点有一个子树(左右皆可)
如图,我们想删除节点10,但是节点10有一个右节点,那么我们可以将节点10的父节点指向节点10的右节点,再释放节点10的内存;
代码:
else if (root->left == NULL) //有右节点
{
struct Node* temp = root;
root = root->right; // 将 root 指针更新为指向当前节点的右子节点
free(temp); //释放
}
else if (root->right == NULL) //有左节点
{
struct Node* temp = root;
root = root->left;
free(temp);
}
情景3:删除的节点具有左节点和右节点
如图,我们想删除掉节点13,那么我们需要找到右子树最小值(左子树最大值)来替换掉删除节点的数据,然后将子树最值节点删除掉;
代码:
struct Node* Min(struct Node* root)
{
if (root->left == NULL) //退出条件
{
return root;
}
Min(root->left); //由于是二叉搜索树,所以左子树存放的是小值
}
if(root->left != NULL&&root->right != NULL)
{
struct Node* temp = Min(root->right); //找出右子树最小值
root->data = temp->data; //将删除值更新为右子树最小值
root->right = delete(root->right, temp->data);//将最值节点删除
}
完整代码:
struct Node* Min(struct Node* root)
{
if (root->left == NULL)
{
return root;
}
Min(root->left);
}
struct Node* delete(struct Node* root, int value) //value是删除节点数据
{
if (root == NULL)
{
return root;
}
else if (root->data > value) //遍历左子树
{
root->left = delete(root->left, value);
}
else if (root->data < value) //遍历右子树
{
root->right = delete(root->right, value);
}
else //找到value对应节点
{
if (root->left == NULL && root->right == NULL) //节点没有左节点和右节点
{
free(root); //释放内存
root = NULL;
}
else if (root->left == NULL) //有右节点
{
struct Node* temp = root;
root = root->right; // 将 root 指针更新为指向当前节点的右子节点
free(temp); //释放
}
else if (root->right == NULL) //同理
{
struct Node* temp = root;
root = root->left;
free(temp);
}
else //同时有左节点和右节点
{
struct Node* temp = Min(root->right); //找出右子树最小值
root->data = temp->data; //将删除值更新为右子树最小值
root->right = delete(root->right, temp->data); //将右子树最小值的节点删除
}
}
return root; //返回指针
}