二叉搜索树
二叉搜索树
@
目录
1. 定义
- 左子树小于根节点
- 右子树大于根节点
2. 求某个节点的后继
概念:比当前节点大的最小节点
- 节点存在右子树
- 先找到右子树
- 一路往左走,直到空树
- 节点不存在右子树
- 后继可能存在于查找到改节点的路上
3. 求节点的前驱
- 比当前节点小的最大节点
- 节点存在左子树
- 先找到左子树
- 一路往右子树走,直到为空
- 节点不存在左子树
- 前驱可能存在查找该节点的路上
4. 删除节点
- 分为三种情况
- 该节点只有左子树,直接拼接左子树
- 该节点只有右子树,直接拼接右子树
- 存在左右子树
- 求该节点的的后继
- 该节点的值与其后继的值交换
- 删除后继(因为后继是右子树一路往左,这样删除后继是,后继最多只存在右子树,所以回到上述前两种情况)
LeetCode
701. 二叉搜索树中的插入操作(二叉搜索树查找插入模板)
给定二叉搜索树(BST)的根节点 root
和要插入树中的值 value
,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。
注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。
示例 1:
输入: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:
输入: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 };
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix