由于二叉搜索树的特性,非递归法不需要额外模拟栈,但是注意,删除结点时必须知道其父结点、以及所删除的结点是父结点的左孩子还是右孩子!
class Solution {
public:
TreeNode* deleteOneNode(TreeNode* cur){
TreeNode* temp=cur; //当前结点暂存,最后释放堆区内存
if(!cur->left && !cur->right){ //叶子结点,直接删除
cur=nullptr;
}
else{
if(cur->left && !cur->right){ //左孩子非空,右孩子空
cur=cur->left;
}
else if(!cur->left && cur->right){ //右孩子非空,左孩子空
cur=cur->right;
}
else{ //左右孩子均非空,则把左孩子作为右孩子最左最底层的结点的左孩子
//寻找右孩子中最左最底结点
TreeNode* p=cur->right; //当前结点
TreeNode* q=nullptr; //当前结点的父结点
while(p){
q=p;
p=p->left;
}
q->left=cur->left;
cur=cur->right;
}
}
delete temp;
return cur;
}
TreeNode* deleteNode(TreeNode* root, int key) {
TreeNode* cur=root; //当前指针
TreeNode* pre=nullptr; //父结点指针
while(cur){
int nodeVal=cur->val;
if(nodeVal==key){ //删除当前结点(注意,删除最顶端结点与其他结点不一样!!)
if(pre==nullptr){ //删除的结点就是最顶端结点
root=deleteOneNode(cur);
}
else{ //其他结点,判断删除的结点是父结点的左孩子?还是右孩子?
if(pre->left && nodeVal==pre->left->val){//要删除的结点是父结点的左孩子
pre->left=deleteOneNode(cur);
}
else if(pre->right && nodeVal==pre->right->val){
pre->right=deleteOneNode(cur);
}
}
break;
}
else{ //非当前结点,需要更新父结点为当前结点,再去看左右孩子
pre=cur;
if(nodeVal< key) cur=cur->right;
else cur=cur->left;
}
}
return root;
}
};