版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hansionz/article/details/81988752
1.思路
思路:在链式结构中,要删除一个结点,我们常规的做法是找到要删除结点的前一个结点,把它的和一个结点,挂在前一个结点上,但是对于二叉搜索树,既要删除一个结点,又要满足二叉搜索树的性质,是相对于比较难的。
二叉搜索树的删除大致分为以下类:
对于以上的四类要删除的结点,其实我们还可以在具体一些,将一二三类归在一起,第四类是一类。
下面是两类删除结点的方法
2.代码实现
- 非递归实现
//删除一个结点(删除成功返回1,失败返回0)
int BSTreeRemove(BSTreeNode** root, BSTDataType x)
{
assert(root);
BSTreeNode* cur = *root;
BSTreeNode* parent = NULL;//记录要删除结点的父节点
while (cur)
{
//1.寻找要删除的结点
if (cur->_data > x)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_data < x)
{
parent = cur;
cur = cur->_right;
}
//2.此时cur指向要删除结点,parent指向要删除结点的父亲
else
{
//①要删除结点的左孩子为空或者右孩子为空
if (cur->_left == NULL)
{
//如果要删除的结点是根结点并且左孩子为空,替换根节点为右树根节点
if (parent == NULL)
{
*root = cur->_right;
free(cur);
}
//不是根节点,则直接判断调整指向
else
{
if (cur == parent->_left)
{
parent->_left = cur->_right;
free(cur);
}
else
{
parent->_right = cur->_right;
free(cur);
}
}
}
else if (cur->_right == NULL)
{
//如果要删除的结点是根结点并且右孩子为空,替换根节点为左树根节点
if (parent == NULL)
{
*root = cur->_left;
free(cur);
}
//不是根节点,则直接判断调整指向
else
{
if (cur == parent->_left)
{
parent->_left = cur->_left;
free(cur);
}
else
{
parent->_right = cur->_left;
free(cur);
}
}
}
//②要删除结点的左右孩子都不为空(替换删除法)
else
{
BSTreeNode* repalce = cur->_right;
//找到要替换的结点(要删除结点右树最左边的那个结点就是替换结点)
while (repalce->_left)
{
repalce = repalce->_left;
}
//替换数据
cur->_data = repalce->_data;
//递归删除替换结点
BSTreeRemove(&cur->_right, repalce->_data);
}
return 1;
}
}
return 0;
}
- 递归实现
//删除一个结点(成功返回1,失败返回0)
int BSTreeRemoveR(BSTreeNode** root, BSTDataType x)
{
assert(root);
//树为空,删除失败
if ((*root) == NULL)
{
return 0;
}
//要删除的数小于根结点的数,说明要删除的结点在左树
if ((*root)->_data > x)
{
BSTreeRemoveR(&(*root)->_left, x);
}
//要删除的数大于根结点的数,说明要删除的结点在右树
else if ((*root)->_data < x)
{
BSTreeRemoveR(&(*root)->_right, x);
}
//*root一定为要删除的结点
else
{
//记录要释放的结点
BSTreeNode* del = *root;
//1.左子树为空或者右子树为空
if ((*root)->_left == NULL)
{
*root = (*root)->_right;
free(del);
}
else if ((*root)->_right == NULL)
{
*root = (*root)->_left;
free(del);
}
//2.左右子树都不为空(替换删除法)
else
{
BSTreeNode* repalce = (*root)->_right;
while (repalce->_left)
{
repalce = repalce->_left;
}
(*root)->_data = repalce->_data;
BSTreeRemoveR(&(*root)->_right, repalce->_data);
}
return 1;
}
}