首页 > 其他分享 >二叉搜索树

二叉搜索树

时间:2023-02-04 11:46:56浏览次数:60  
标签:right val 二叉 搜索 null root 节点

二叉搜索树

@

目录

1. 定义

  • 左子树小于根节点
  • 右子树大于根节点

2. 求某个节点的后继

概念:比当前节点大的最小节点

  • 节点存在右子树
    • 先找到右子树
    • 一路往左走,直到空树
  • 节点不存在右子树
    • 后继可能存在于查找到改节点的路上

3. 求节点的前驱

  • 比当前节点小的最大节点
  • 节点存在左子树
    • 先找到左子树
    • 一路往右子树走,直到为空
  • 节点不存在左子树
    • 前驱可能存在查找该节点的路上

4. 删除节点

  • 分为三种情况
    • 该节点只有左子树,直接拼接左子树
    • 该节点只有右子树,直接拼接右子树
    • 存在左右子树
      • 求该节点的的后继
      • 该节点的值与其后继的值交换
      • 删除后继(因为后继是右子树一路往左,这样删除后继是,后继最多只存在右子树,所以回到上述前两种情况

LeetCode

701. 二叉搜索树中的插入操作(二叉搜索树查找插入模板)

给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。

注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果

示例 1:

img

输入:root = [4,2,7,1,3], val = 5
输出:[4,2,7,1,3,5]
解释:另一个满足题目要求可以通过的树是:

示例 2:

输入:root = [40,20,60,10,30,50,70], val = 25
输出:[40,20,60,10,30,50,70,null,null,25]

示例 3:

输入:root = [4,2,7,1,3,null,null,null,null,null,null], val = 5
输出:[4,2,7,1,3,5]

提示:

  • 树中的节点数将在 [0, 104]的范围内。
  • -108 <= Node.val <= 108
  • 所有值 Node.val独一无二 的。
  • -108 <= val <= 108
  • 保证 val 在原始BST中不存在。
完整代码
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @param {number} val
 * @return {TreeNode}
 */
var insertIntoBST = function(root, val) {

    if(!root){
        return new TreeNode(val)
    }

    //  更好的一种写法,可能不好理解

    if(val<root.val){
        root.left=insertIntoBST(root.left,val)
    }else{
        root.right=insertIntoBST(root.right,val)
    }

    return root

};

二叉搜索树寻找后继模板

设计一个算法,找出二叉搜索树中指定节点的“下一个”节点(也即中序后继)。

如果指定节点没有对应的“下一个”节点,则返回null

示例 1:

输入: root = [2,1,3], p = 1

  2
 / \
1   3

输出: 2

示例 2:

输入: root = [5,3,6,2,4,null,null,1], p = 6

      5
     / \
    3   6
   / \
  2   4
 /   
1

输出: null
完整代码
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @param {TreeNode} p
 * @return {TreeNode}
 */
var inorderSuccessor = function(root, p) {

    // 即找出二叉搜索树的后继

    // 即比当前节点大的最小节点

    // 如果存在右子树,先右子树,然后一路往左走

    // 1.如果不存在右子树,则后继节点可能在祖先

    // 2.从根节点开始查找,如果往左走,说明查找的节点在左边,那么当前节点是不是比目标节点大

    // 3.所有只要往左走,我们就记录当前节点,因为它比目标节点大,且很靠经目标节点

    let res=null

    const search=(root,p)=>{
        if(p.val>root.val){
            search(root.right,p)
        }else if(p.val<root.val){
            res=root
            search(root.left,p)
        }else{
            // 相等
            // 判断是否有右子树
            if(!root.right) return 

            // 存在
            // 找到右子树,一路左走
            let node=root.right
            while(node.left!=null){
                node=node.left
            }
            res=node
        }
    }

    search(root,p)   
    return res

};

450. 删除二叉搜索树中的节点模板

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

一般来说,删除节点可分为两个步骤:

  1. 首先找到需要删除的节点;
  2. 如果找到了,删除它。

示例 1:

img

输入:root = [5,3,6,2,4,null,7], key = 3
输出:[5,4,6,2,null,null,7]
解释:给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
另一个正确答案是 [5,2,6,null,4,null,7]。

示例 2:

输入: root = [5,3,6,2,4,null,7], key = 0
输出: [5,3,6,2,4,null,7]
解释: 二叉树不包含值为 0 的节点

示例 3:

输入: root = [], key = 0
输出: []

提示:

  • 节点数的范围 [0, 104].
  • -105 <= Node.val <= 105
  • 节点值唯一
  • root 是合法的二叉搜索树
  • -105 <= key <= 105

进阶: 要求算法时间复杂度为 O(h),h 为树的高度。

完整代码
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @param {number} key
 * @return {TreeNode}
 */
var deleteNode = function(root, key) {

    // 更简洁的一种写法,比较难懂

    if(!root) return null

    // 找到,分三种情况,只有左子树,只要右子树,左右子树都有

    if(root.val===key){
        if(root.left===null) return root.right
        if(root.right===null) return root.left


        // 左右子树都存在
        let next=root.right
        
        // 一路向左找到后继
        while(next.left){
            next=next.left
        }

        // 删除后继
        // 在后继树中删除next节点
        root.right=deleteNode(root.right,next.val)
        root.val=next.val
        return root
    }


    if(root.val<key){
        root.right=deleteNode(root.right,key)
    }else{
        root.left=deleteNode(root.left,key)
    }

    return root

};

标签:right,val,二叉,搜索,null,root,节点
From: https://www.cnblogs.com/lingxin1123/p/17087611.html

相关文章