二叉搜索树
@
目录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
};
标签:right,val,二叉,搜索,null,root,节点
From: https://www.cnblogs.com/lingxin1123/p/17087611.html