450. 删除二叉搜索树中的节点
递归法(二叉搜索树):
cppclass Solution{ public: TreeNode* deleteNode(TreeNode* root, int key){ if(!root) return root; if(key==root->val){ if(!root->left&&!root->right){ delete root; return NULL; } else if(!root->left){ TreeNode* rn=root->right; delete root; return rn; } else if(!root->right){ TreeNode* ln=root->left; delete root; return ln; } else{ TreeNode* tn=root->right; while(tn->left){ tn=tn->left; } tn->left=root->left; TreeNode* tmp=root; root=root->right; delete tmp; return root; } } if(key<root->val) root->left=deleteNode(root->left,key); if(key>root->val) root->right=deleteNode(root->right,key); return root; } };递归法(普通二叉树):
cppclass Solution{ public: TreeNode* deleteNode(TreeNode* root,int key){ if(!root) return NULL; if(root->val==key){ if(!root->right) return root->left; TreeNode* tn=root->right; while(tn->left){ tn=tn->left; } swap(root->val,tn->val); } root->left=deleteNode(root->left,key); root->right=deleteNode(root->right,key); return root; } };迭代法:
cppclass Solution{ private: TreeNode* deleteOneNode(TreeNode* root){ if(!root) return root; else if(!root->left) return root->right; else if(!root->right) return root->left; else{ TreeNode* tn=root->right; while(tn->left){ tn=tn->left; } tn->left=root->left; return root->right; } } public: TreeNode* deleteNode(TreeNode* root,int key){ if(!root) return root; TreeNode* cur=root; TreeNode* pre=NULL; while(cur){ if(key==cur->val) break; pre=cur; if(key<cur->val) cur=cur->left; else if(key>cur->val) cur=cur->right; } if(!pre) return root; else if(pre->left==cur) pre->left=deleteOneNode(cur); else if(pre->right==cur) pre->right=deleteOneNode(cur); return root; } };
其他:
(1)递归新理解:有返回值的递归存在一个上层类别节点选择递归路径 、下层类别节点向上递出返回值 、上层类别节点接受返回值 的过程。所以考虑的时候可以用从下向上 和从上向下的两种方式进行。
(2)判断时分支容易写错的问题:
cppif(!root->left&&!root->right){ delete root; return NULL; } else if(root->left){ TreeNode* ln=root->left; delete root; return ln; } else if(root->right){ TreeNode* rn=root->right; delete root; return rn; } else{ TreeNode* tn=root->right; while(tn->left){ tn=tn->left; } tn->left=root->left; TreeNode* tmp=root; root=root->right; delete tmp; return root; }对于本题来说,上面的分支是错误的,因为分支1是左右双空,原本想要的分支4是左右都非空,但此时分支2和分支3两个分支与分支4有重合。下面的分支则是正确的:
cppif(!root->left&&!root->right){ delete root; return NULL; } else if(!root->left){ TreeNode* rn=root->right; delete root; return rn; } else if(!root->right){ TreeNode* ln=root->left; delete root; return ln; } else{ TreeNode* tn=root->right; while(tn->left){ tn=tn->left; } tn->left=root->left; TreeNode* tmp=root; root=root->right; delete tmp; return root; }这里对自己来说有些容易写错,记录一下,一定要保证if else分支之间的情况是完全隔离的
(3)对于递归法 来说,访问操作 通常发生在当前层 ,而对于迭代法 来说,访问 通常发生在上一层
对于递归法 来说,访问和操作 通常发生在一起 ,而对于迭代法 来说,访问和操作 可以分成两步 ,操作 可以单独写一个函数
(4)二叉搜索树的迭代法遍历访问特定值的节点
cppwhile(cur){ if(key==cur->val) break; pre=cur; if(key<cur->val) cur=cur->left; else cur=cur->right; }(5)pre 在二叉搜索树 的迭代法寻找中有两个作用:
a.一是判断是否停在根节点
b.二是停在非根节点 的时候,找前一个节点的指针 进行操作