二叉搜索树节点的删除较节点的插入和查找难以理解,涉及到以下情况:
节点为空时直接返回false;
if (_root == NULL)
{
return false;
}
有一个节点的时候,判断要删除的值是否和节点的权值相等,相等删除并返回true;不想等删除失败返回false;
if (_root->_left == NULL&&_root->_right == NULL)
{
if (_root->_key == key)
{
delete _root;
_root = NULL;
return true;
}
return false;
}
当树的节点众多时,首先找到需要删除节点cur的位置,记录节点的父亲节点parent
1.当cur的左子树为空的时候
要删除节点cur的parent节点为空,其实删除的就是这棵树的根节点,让cur的右节点作为根节点,delete掉cur,置空。
删除节点cur的parent不为空
cur在parent的左子树:
cur在parent的右子树:
if (cur->_left == NULL)
{
del = cur;
if (parent == NULL)
{
_root = cur->_right;
delete del;
del = NULL;
return true;
}
if (parent->_left == cur)
{
parent->_left = cur->_right;
delete del;
del = NULL;
return true;
}
else if (parent->_right == cur)
{
parent->_right = cur->_right;
delete del;
del = NULL;
return true;
}
}
2.当cur的右子树为空的时候
要删除节点cur的parent节点为空,其实删除的就是这棵树的根节点,让cur的左节点作为根节点,delete掉cur,置空。
删除节点cur的parent节点不为空的时候
cur节点在parent的左子树:
cur节点在parent的右子树:
else if (cur->_right == NULL)
{
del = cur;
if (parent == NULL)
{
_root = cur->_left;
delete del;
del = NULL;
return true;
}
if (parent->_left == cur)
{
parent->_left = cur->_left;
delete del;
del = NULL;
return true;
}
else if (parent->_right == cur)
{
parent->_right = cur->_left;
delete del;
del = NULL;
return true;
}
}
3.当左右子树都不为空的时候
if (cur->_left != NULL&&cur->_right != NULL)
{
del = cur;
Node* sub = cur->_right;
Node* sub_parent = cur;
while (sub->_left)
{
sub_parent = sub;
sub = sub->_left;
}
cur->_key = sub->_key;
if (sub_parent->_right == sub)
{
sub_parent->_right = sub->_right;
}
else
{
sub_parent->_left = sub->_right;
}
delete sub;
sub = NULL;
return true;
}
递归代码:
void Remove_R(const T& key)
{
_Remove_R(_root, key);
}
bool _Remove_R(Node*& root, const T& key)
{
if (root == NULL)
{
return false;
}
if (root->_left == NULL&&root->_right == NULL)
{
if (root->_key == key)
{
delete root;
root = NULL;
return true;
}
}
//先找到要删除的节点
if (root->_key > key)
{
_Remove_R(root->_left, key);
}
else if (root->_key < key)
{
_Remove_R(root->_right, key);
}
else
{
Node* del = NULL;
if (root->_left == NULL)
{
del = root;
root = root->_right;
delete del;
}
else if (root->_right == NULL)
{
del = root;
root = root->_left;
delete del;
}
else if (root->_left != NULL&&root->_right != NULL)
{
Node* subright = root->_right;
while (subright->_left)
{
subright = subright->_left;
}
root->_key = subright->_key;
//将右子树的最左节点和root节点的权值换了之后,需要删除的点替换成右子树的最左节点
//再递归调用一次函数,将右子树的根节点和需要删除的权值传进去,即可删除。
_Remove_R(root->_right, subright->_key);
}
}
return false;
}