1. 算法
1.1 二叉搜索树插入元素
题目来源:力扣
给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。
注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。
图1. 二叉搜索树插入操作
分析,二叉搜素树中插入数字,关键在于设置怎样的规则,插入在什么位置。在示例1中,方法1的做法为在对的叶子节点位置末端插入新的元素,该方法基本不改变树的结构;而方法二为将树拎起来了,在根节点的位置插入相应元素,其余元素按照二叉树的性质进行调整。这里,选用第一种方法,
从树根开始:
(1)若val<当前节点的值,转向左节点;
(2)若val>当前节点的值,转向右节点;
直到左节点或者右节点为None,也就是遇到的父节点为叶子节点为止,在相应的子节点位置插入相应元素。
根据该算法步骤知,在二叉搜索树中插入元素为递归操作。
1.2 二叉搜索树删除元素
题目来源:力扣
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
1. 首先找到需要删除的节点;
2. 如果找到了,删除它。
图2. 二叉搜索树的删除操作
相比于元素的插入操作,二叉搜索树删除元素的操作要复杂得多。正如提示中所言,第一步,找到要删除的节点,然后删除它。我也知道找到了要删除他\好逗啊,但是问题是怎么删除,怎么将底下的节点合理地挪上去。
首先,区分要删除的元素是根节点元素还是其他普通节点的元素,根节点元素的删除操作略简单一些。首先,分析普通位置的元素删除的方法,先来看一张图,
图3. 删除元素辅助图
这里,我们规定将左子树填补到删除的位置(如果是将右子树填补到删除的位置,思路一致)。在图3中,删除2对应的节点,那么将其左子树,也就是左边框部分挪到2所在位置。但是,此时出现一个问题,如果是二叉树的话,4节点挪到2,其原本有自己的右子节点7,但是同时新的右子节点5会和7冲突,因此,采用递归的方式将7挪到左边框的最右边的位置(因为4,6,7,7是右边子树,比左子树的任何值都大,因此7应该在12右边插入,而非随便一个叶子节点的子树位置)。
在这个过程中,前后连接的重要节点为1和4,要将父节点的左指针指向删除元素的左子节点(右子节点同理)。
分以下几种情况讨论:
(1)删除节点为叶子节点,既无左子节点,也无右子节点,直接删掉即可;
(2)删除节点只有左子树,没有右子树,则将父节点的左指针指向左子树即可;
(3)删除节点只有右子树,没有左子树,则将父节点的右指针指向右子树即可;
(4)删除节点即有左子树,也有右子树,则将其右子树挪到左子树的右下角。
在挪到右下角的过程中,首先要将父节点指向左子树,然后将右子树挪到右下角。
2. 代码
代码如下:
# Definition for a binary tree node.
class TreeNode(object):
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def set_left(self, left):
self.left = left
def set_right(self, right):
self.right = right
class Solution(object):
def insertIntoBST(self, root, val):
"""
:type root: TreeNode
:type val: int
:rtype: TreeNode
"""
if root == None:
return TreeNode(val)
current = root
if val < current.val:
if current.left != None:
self.insertIntoBST(current.left, val)
else:
current.left = TreeNode(val)
elif val > current.val:
if current.right != None:
self.insertIntoBST(current.right, val)
else:
current.right = TreeNode(val)
return root
def deleteNode(self, root, key):
"""
:type root: TreeNode
:type key: int
:rtype: TreeNode
"""
if root == None:
return
if root.val == key:
node = root
if node.left == None and node.right == None:
return None
elif node.left != None and node.right == None:
root = node.left
elif node.left == None and node.right != None:
root = node.right
elif node.left != None and node.right != None:
left = node.left
right = node.right
root = left
while left.right != None:
left = left.right
left.right = right
return root
current = [root]
while current != []:
tmp = []
for node in current:
if node.left != None and node.left.val == key:
if node.left.left == None and node.left.right == None:
node.left = None
elif node.left.left != None and node.left.right == None:
node.left = node.left.left
elif node.left.left == None and node.left.right != None:
node.left = node.left.right
elif node.left.left != None and node.left.right != None:
left = node.left.left
right = node.left.right
node.left = left
while left.right != None:
left = left.right
left.right = right
current = []
break
if node.right != None and node.right.val == key:
if node.right.left == None and node.right.right == None:
node.right = None
elif node.right.left != None and node.right.right == None:
node.right = node.right.left
elif node.right.left == None and node.right.right != None:
node.right = node.right.right
elif node.right.left != None and node.right.right != None:
left = node.right.left
right = node.right.right
node.right = left
while left.right != None:
left = left.right
left.right = right
current = []
break
if node.left != None:
tmp.append(node.left)
if node.right != None:
tmp.append(node.right)
current = tmp
return root