二叉搜索树
二叉搜索树是特殊的二叉树。若一颗二叉树,它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 我们把这样的二叉树成为二叉搜索树,它的左、右子树也分别为二叉搜索树。
二叉搜索树的例子:
二叉搜索树的查找
给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。
如题
返回
解题思路:给定二叉搜索树,我们只需要在二叉搜索树的结构里找到与val对应的位置并输出节点就可以了。二叉搜索树具有根节点大于左子树值且小于右子树值的特点。
方法一:递归
class Solution:
def searchBST(self, root: TreeNode, val: int) -> TreeNode:
if not root or val == root.val:
return root
return self.searchBST(root.left, val) if val < root.val \
else self.searchBST(root.right, val)
方法二:迭代
class Solution:
def searchBST(self, root: TreeNode, val: int) -> TreeNode:
while root is not None and val != root.val:
root = root.left if val < root.val else root.right
return root
二叉搜索树的插入
给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。
示例
解题思路:首先回顾二叉搜索树的性质:对于任意节点 root 而言,左子树(如果存在)上所有节点的值均小于root.val,右子树(如果存在)上所有节点的值均大于 root.val,且它们都是二叉搜索树。
因此,当将 val 插入到以 root 为根的子树上时,根据val 与root.val 的大小关系,就可以确定要将 val 插入到哪个子树中。
如果该子树不为空,则问题转化成了将 val 插入到对应子树上。
否则,在此处新建一个以val 为值的节点,并链接到其父节点 root 上。
class Solution:
def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:
if not root:
return TreeNode(val)
pos = root
while pos:
if val < pos.val:
if not pos.left:
pos.left = TreeNode(val)
break
else:
pos = pos.left
else:
if not pos.right:
pos.right = TreeNode(val)
break
else:
pos = pos.right
return root
二叉搜索树的删除
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。
解题思路:
这里有三种可能的情况:
要删除的节点为叶子节点,可以直接删除。
要删除的几点不是叶子节点且拥有右节点,则该节点可以由该节点的后继节点进行替代,该后继节点位于右子树中较低的位置。然后可以从后继节点的位置递归向下操作以删除后继节点。
要删除的节点不是叶子节点,且没有右节点但是有左节点。这意味着它的后继节点在它的上面,但是我们并不想返回。我们可以使用它的前驱节点进行替代,然后再递归的向下删除前驱节点。
class Solution:
def successor(self, root):
"""
One step right and then always left
"""
root = root.right
while root.left:
root = root.left
return root.val
def predecessor(self, root):
"""
One step left and then always right
"""
root = root.left
while root.right:
root = root.right
return root.val
def deleteNode(self, root: TreeNode, key: int) -> TreeNode:
if not root:
return None
# delete from the right subtree
if key > root.val:
root.right = self.deleteNode(root.right, key)
# delete from the left subtree
elif key < root.val:
root.left = self.deleteNode(root.left, key)
# delete the current node
else:
# the node is a leaf
if not (root.left or root.right):
root = None
# the node is not a leaf and has a right child
elif root.right:
root.val = self.successor(root)
root.right = self.deleteNode(root.right, root.val)
# the node is not a leaf, has no right child, and has a left child
else:
root.val = self.predecessor(root)
root.left = self.deleteNode(root.left, root.val)
return root