二叉搜索树的删除
1.思路是:
先找到删除节点的位置。
然后判断是否找到了这个元素。
如果找到了。
就删除节点。
而删除节点又分为四种情况
1.删除节点没有子节点
如上图我们假如要删除 9 直接删除该节点即可
.
.
2.删除节点没有右子树
如上图,假如我们要删除1,那麽我们就不能直接删除该节点 ,因为他还有子节点,如果我们直接让1的父节点的左孩子直接置为null,就会丢失1的子节点。所以应该将1的节点连接在节点3下面。
3.删除节点没有左子树
如上图,假如我们要删除1,那麽我们就不能直接删除该节点 ,因为他还有子节点,如果我们直接让1的父节点的左孩子直接置为null,就会丢失1的子节点。所以应该将1的节点连接在节点3下面。
4.删除节点既有左子树又有右子树
因为需要删除的节点既有左子树又有右子树这时候就需要找到新的根节点
新的根节点:
左子树的最右节点–>左子树中最大的节点
右子树的最左节点–>右子树中最小的节点
任意找到一个作为根节点即可
如上图 ,5节点的左子树的最右节点就是4
5节点的右子树的最左节点就是6
寻找左子树的最右节点代码如下
node* leftrightmost = cur->_left;
parent = cur;
while (leftrightmost->_right) {
parent = leftrightmost;
leftrightmost = leftrightmost->_right;
}
总体代码实现
//删除元素
bool erase(const T& val) {
//查找结点
node* cur = _root;
node* parent = nullptr;
while (cur) {
if (cur->_data > val)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_data < val) {
parent = cur;
cur = cur->_right;
}
else
break;
}
//判断是否找到了
if (cur == nullptr)
return false;
//删除
//1.删除的节点为子节点
if (cur->_left == nullptr && cur->_right == nullptr) {
//判断删除的节点是否为根节点
if (cur == _root) {
_root = nullptr;
}
else {
//判断需要删除的节点在父节点的那一边
if (parent->_left == cur) {
parent->_left = nullptr;
}
else if (parent->_right == cur) {
parent->_right = nullptr;
}
}
//删除节点
delete cur;
}
//2.删除的节点有左孩子
else if (cur->_right == nullptr && cur->_left != nullptr) {
node* next = cur->_left;
//判断需要删除的节点在父节点的哪一边
if (cur == _root) {
_root = cur->_left;
}
else {
if (parent->_left == cur) {
parent->_left = next;
}
else if (parent->_right == cur) {
parent->_right = next;
}
}
delete cur;
}
//3.删除的节点有右孩子
else if (cur->_left == nullptr) {
node* next = cur->_right;
if (cur == _root) {
_root = cur->_right;
}
else
{
//判断需要删除的节点在父节点的哪一边
if (parent->_left == cur) {
parent->_left = next;
}
else if (parent->_right == cur) {
parent->_right = next;
}
}
delete cur;
}
//4.删除的节点既有左孩子又有右孩子
else if (cur->_left != nullptr && cur->_right != nullptr) {
//假设找左子树的最右节点
node* leftrightmost = cur->_left;
parent = cur;
while (leftrightmost->_right) {
parent = leftrightmost;
leftrightmost = leftrightmost->_right;
}
//交换
swap(leftrightmost->_data, cur->_data);
//删除最右节点
if (parent->_left == leftrightmost)
parent->_left = leftrightmost->_left;
else
parent->_right = leftrightmost->_left;
delete leftrightmost;
}
return true;
}