#学习记录#
今天继续来撕二叉搜索树
对应力扣:
1.二叉搜索树中的插入操作: 701.二叉搜索树中的插入操作
2.删除二叉搜索树中的节点: 450.删除二叉搜索树中的节点
1.二叉搜索树中的插入操作
1.1题目描述
1.2 思路
题目中也提到,我们可能有不同的插入方式,实际上怎么简单怎么来的话,我们直接找遍历到最后的叶子节点,找到之后插入就行,一定会有位置!
根据二叉搜索树的特性,我们直接上迭代法,比较好理解。
1.3 代码(python)
class Solution(object):
def insertIntoBST(self, root, val):
"""
:type root: TreeNode
:type val: int
:rtype: TreeNode
"""
result = root
if not root:
root = TreeNode(val = val)
return root
# 在这里我们要提前设置一个pre,方便我们做插入操作,否则之间遍历到空节点
pre = None
while root:
pre = root
if root.val > val:
root = root.left
else :
root = root.right
if pre.val > val:
pre.left = TreeNode(val)
else:
pre.right = TreeNode(val)
return result
2.删除二叉搜索树中的节点
2.1题目描述
2.2 思路
这道题看起来还是有点懵的,如果是叶子节点的话好说,直接删除就是了。但是还涉及了不同位置的节点删除,所以稍显复杂。我们将所有情况罗列出来。
- 如果根节点为空,直接返回空节点
- 如果要删除的节点右节点为空,左节点不为空,当前节点(cur)直接继承(cur.left)即可,如下
5
/ \
3 8
/ \
1 7
删除节点3
5
/ \
1 8
\
7
- 删除的节点左节点为空,右节点不为空,当前节点(cur)直接继承(cur.right)即可,情况类似2
- 删除节点为叶子节点:直接删除即可
- 左右节点均不为空(这种情况最为复杂)针对这种情况,我们首先设置一个min_node遍历cur的右子树的左节点,找到其右子树的最小值,另外设置一个min_node_parent最为min_node父节点。找到以后,将min_node的值赋给cur即可。我们就完成了对cur的删除操作。此时,有两种情况,一种情况是min_node是min_node_parent的右孩子,这时代表min_node没有左节点,这种情况我们直接令cur.right = min_node.right。另外一种情况是,cur的右节点有左节点。此时我们还要考虑min_node是否有右节点,如果有,我们把右节点赋给min_node_parent的左节点即可。
上图:
情况一:min_node是min_node_parent的右孩子
最终:
情况二:min_node是min_node_parent的左节点:
最终:
2.3 代码(python)
直接上代码:
class Solution(object):
def deleteNode(self, root, key):
"""
:type root: TreeNode
:type key: int
:rtype: TreeNode
"""
if not root:
return root
pre = None
cur = root
while cur:
if cur.val == key:
break # 找到了要删除的节点
pre = cur
cur = cur.left if cur.val > key else cur.right
if not cur: # 没有找到要删除的节点
return root
# 如果当前节点是叶子节点
if not cur.left and not cur.right:
if cur == root: # 要删除的是根节点
return None
if pre.left == cur:
pre.left = None
else:
pre.right = None
# 如果当前节点只有一个子节点
elif not cur.left or not cur.right:
child = cur.left if cur.left else cur.right
if cur == root: # 要删除的是根节点
return child
if pre.left == cur:
pre.left = child
else:
pre.right = child
# 如果当前节点有两个子节点
else:
min_node_parent = cur
min_node = cur.right # 找到右子树
while min_node.left: # 找到右子树中的最小节点
min_node_parent = min_node
min_node = min_node.left
cur.val = min_node.val # 用最小节点的值替换当前节点的值
# 删除最小节点,这个节点不会有左子节点
if min_node_parent.right == min_node:
cur.right = min_node.right
else:
min_node_parent.left = min_node.right
# 有亿点复杂:将cur的右子树的最左边节点(min_node)放在原来的cur的位置上,然后不确定min_node有没有右节点,有就有,没有就是None
# 无论有或没有我们都可以把min_node得右节点赋给min_node父节点(min_node_parent.right)
# 如果min_node_parent.left != min_node,就代表了min_node_parent是min_node的右节点,直接将min_node的右节点连接到cur上即可
return root
值得注意的一点:
在对节点进行覆盖时,可能有同学会写出:cur = cur.right这样形式的赋值,这样是不正确的。因为,cur只是节点的一个副本,对cur进行修改不会对原树进行改变。想要对cur进行修改的话,我们就要使用到pre节点,也就是它的父节点。
if pre.left == cur:
pre.left = cur.right
else :
pre.right = cur.right
以上
学习在于总结和坚持,共勉