问题:删除二叉搜索树中的节点
解题思路
通过二叉搜索树的性质对待删除节点进行定位,设待删除节点为x则有一下两种情况
- 情况一:x有两个孩子
- 情况二:x至多只有一个孩子
当x有两个孩子时我们要用x的前驱节点或者x的后继节点替代x,将其值赋给x,然后删除x的前驱或者后继节点,此时就是情况二,对于情况二,如果x没孩子,直接将x删除,如果x有一个孩子,则将x的那个孩子链接到x的父节点上即可。
C++代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if(!root) return NULL;
TreeNode *parent = NULL, *x = root;//parent记录x的父节点,x表示待删除的点
while(x && x->val != key){//找到待删除的点
parent = x;//更新x的父节点
if(x->val < key)//在x的右子树中
x = x->right;
else//在x的左子树中
x = x->left;
}
if(!x) return root;//没找到,返回根节点
//x是要被删除的点,如果x只有至多一个孩子则可以删除,否则需要用x的前驱或者后继节点替代它,即将x的前驱节点的值赋给x即可
//x的前驱节点:x的左子树中的最大节点
//x的后继节点:x的右子树中的最小节点
//此次我们用x的前驱节点
TreeNode *y = x;//y表示真正要被删除的节点,初始为x
if(x->left && x->right){//如果x有两个孩子,则用x的前驱节点替代x
parent = y;
y = x->left;
while(y->right){
parent = y;
y = y->right;
}
}
//此时y是待删除的节点且之多只有一个孩子
if(!y->left && !y->right){ //情况一:y没有孩子,直接将y删掉
if(parent){//删除y之前要将parent对应的指针设为NULL
if(y->val < parent->val)
parent->left = NULL;
else
parent->right = NULL;
}
if(!parent) root = NULL;//如果parent为NULL,说明删除的是root,令root为NULL
}
else{ //情况二:y有一个孩子
TreeNode *child;
if(y->left) child = y->left;
if(y->right) child = y->right;
if(parent){//确定child是parent的哪个孩子
if(parent->val < child->val)
parent->right = child;//child是parent的右孩子
else
parent->left = child;//child是parent的左孩子
}
if(!parent) root = child;//parent为NULL,说明删除的是root,那么child成为新的根节点
}
if(y != x) x->val = y->val;//如果x和y不是同一个节点,则y是x的前驱节点,将y的值赋给x
delete y;//释放y所占的空间
return root;//返回根节点
}
};