JS:二叉搜索树(1)——中序遍历,基础操作

Binary Search Tree
简单总结下吧,BST 相关的问题,要么利用 BST 左小右大的特性提升算法效率,要么利用中序遍历的特性满足题目的要求,也就这么些事儿吧。

230. 二叉搜索树中第K小的元素

给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。

BST 的中序遍历其实就是升序排序的结果

var kthSmallest = function(root, k) {
    let res = 0, rank = 0;
    function traverse(root) {
        if(root == null) return
        traverse(root.left)
        rank++;
        if(rank == k) {
            res = root.val
            return
        }
        traverse(root.right)
    }
    traverse(root)
    return res
};

538. 把二叉搜索树转换为累加树 (中等)

给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值 等于 原树中大于或等于 node.val 的值之和。

观察下图,值的大小与原来相反
在这里插入图片描述
明显利用中序遍历的相反方式:右跟左,就是逆序排列
一开始就想到左节点怎么拿到父亲节点这个问题,但由于是累加的关系,节点的值是逐渐增大大的,所以可以用全局变量来记录。就变成了简单的遍历问题。

var convertBST = function(root) {
    let sum = 0
    function build(root) {
        if(root == null) return
        build(root.right)
        sum += root.val
        root.val = sum
        build(root.left)
    }
    build(root)
    return root
};

手把手带你刷二叉搜索树(第二期)
本文来实现 BST 的基础操作:判断 BST 的合法性、增、删、查。其中「删」和「判断合法性」略微复杂。

98. 验证二叉搜索树 (中等) fail

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

需要注意:
在这里插入图片描述
方法:通过使用辅助函数,增加函数参数列表,在参数中携带额外信息,将这种约束传递给子树的所有节点
在这里插入图片描述

只关注当前根节点,
第一,验证根节点是否符合父亲给他的规范——在【min,max】区间中。初始情况,肯定没有大小限制。

第二,当前根节点对他的左孩子的要求:min最小值——没有约束,即不变。max最大值要小于自己root.val。
不变的意思是:可能当前根节点的父亲有min最小值的约束,比如上述的6,它的最小值10是父亲的父亲来规定的。

有人疑惑,这个10的规定是怎么传给了6的呢?在看当前根节点对他的右孩子的要求:min最小值要大于直接root.val。看出来是从这时要去的。max最大值就没有约束,也是不变。

有人可能像我一样,质疑这样就能满足全部的状况吗?之前提过,我们不要去脑补递归。我们可以随便选一个根节点,处理好当前节点,和函数应该对下一层递归做好什么约束就可以了。

写这么多也是为了理解,背递归代码是没有用的。

边界问题:
[2,2,2]
预期结果:false
所以是开区间

如果没有约束,我们初始化min和max为null,后面就判断是否为null来确定有无约束

function check(root, min, max) {
    if(root == null) return true
    if(min!=null && root.val <= min) return false
    if(max!=null && root.val >= max) return false
    return check(root.left, min, root.val) && check(root.right, root.val, max)
}

var isValidBST = function(root) {
    return check(root, null, null)
};

700. 二叉搜索树中的搜索 (简单)

给定二叉搜索树(BST)的根节点 root 和一个整数值 val。
你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。

在这里插入图片描述

var searchBST = function(root, val) {
    if(root == null) return null
    if(root.val == val) return root
    if(root.val < val){
        return searchBST(root.right, val)
    } else {
        return searchBST(root.left, val)
    }
};

701. 二叉搜索树中的插入操作 (中等)fail递归

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

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

一旦涉及「改」,函数就要返回 TreeNode 类型,并且对递归调用的返回值进行接收。

二叉树的查找,只会从上到下走一次,走到最后就是插入的位置。
递归代码:

var insertIntoBST = function(root, val) {
    if(root == null) return new TreeNode(val)
    if(root.val < val){
        root.right = insertIntoBST(root.right, val)
    } else {
        root.left = insertIntoBST(root.left, val)
    }
    return root // 最后要求返回根节点
};

也可以先找到最后一个非空节点,这就是迭代。

var insertIntoBST = function(root, val) {
    if(root == null) return new TreeNode(val)
    let node = root, fa = null
    while (node) {
        if(node.val<val){
            fa = node
            node = node.right
        }else if(node.val>val) {
            fa = node
            node = node.left
        }
    }
    let child = new TreeNode(val)
    fa.val < val ? fa.right=child : fa.left=child
    return root // 最后要求返回根节点
};

450. 删除二叉搜索树中的节点 (中等)

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

一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。

没做之前也知道要分情况:试着自己列举一下
1.删除的是子节点。直接删除
2.删除的节点只有一个分支。直接让这个分支的根节点代替自己。
3.删除的节点两边都有分支。找左子树的最右边节点代替自己,或者找右子树的最左边。

习惯一下对递归调用的返回值进行接收。 递归函数的含义:修改过后的子树
写代码时要分清当前的root是指哪一个

function del(root) {
    if(root.left==null && root.right==null) return null
    if(root.left==null || root.right==null) return root.left? root.left : root.right
    let min = root.right
    while(min.left) min = min.left;
    // 先删除右子树最小的节点
    root.right = deleteNode(root.right, min.val)
    // 用右子树最小的节点替换 root 节点
    min.left = root.left
    min.right = root.right
    return min
}
var deleteNode = function(root, key) {
    if(root == null) return null
    if(root.val == key){
        root = del(root)
    } else if(root.val < key){
        root.right = deleteNode(root.right, key)
    } else{
        root.left = deleteNode(root.left, key)
    }
    return root
};
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C语言实现二叉排序树的基本操作的示例代码: 1. 二叉排序树的建立: ```c #include <stdio.h> #include <stdlib.h> struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; }; struct TreeNode* insert(struct TreeNode* root, int val) { if (root == NULL) { struct TreeNode* newNode = (struct TreeNode*)malloc(sizeof(struct TreeNode)); newNode->val = val; newNode->left = NULL; newNode->right = NULL; return newNode; } if (val < root->val) { root->left = insert(root->left, val); } else if (val > root->val) { root->right = insert(root->right, val); } return root; } ``` 2. 二叉排序树的删除: ```c struct TreeNode* delete(struct TreeNode* root, int val) { if (root == NULL) { return NULL; } if (val < root->val) { root->left = delete(root->left, val); } else if (val > root->val) { root->right = delete(root->right, val); } else { if (root->left == NULL) { struct TreeNode* temp = root->right; free(root); return temp; } else if (root->right == NULL) { struct TreeNode* temp = root->left; free(root); return temp; } struct TreeNode* temp = findMin(root->right); root->val = temp->val; root->right = delete(root->right, temp->val); } return root; } struct TreeNode* findMin(struct TreeNode* node) { while (node->left != NULL) { node = node->left; } return node; } ``` 3. 二叉排序树的中序遍历结果: ```c void inorderTraversal(struct TreeNode* root) { if (root == NULL) { return; } inorderTraversal(root->left); printf("%d ", root->val); inorderTraversal(root->right); } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值