LeetCode,二叉搜索树插入、删除元素

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值