算法和数据结构:二叉搜索树常见操作

199 阅读1分钟

以 leetcode 上常见的一些题为例进行说明。

二叉搜索树的操作同样也与树的遍历方式息息相关,不了解的可以参考我的上上篇博客。

判断是否是二叉搜索树

首先想到只要遍历每个节点,判断左子小于。右子大于,即可,但是发现只满足这两个调价你的不一定的二叉搜索树,比如这棵树 [10,5,15,null,null,6,20],其实还需要加一个条件,就是不仅仅要左子小于。右子大于,是整个左子树小于,整个右子树大于,看上去比较烦。我们换一种思路。

我们知道中序遍历的过程就是二叉搜索树升序遍历的过程,每遍历到一个点与上一个点进行比较,并将其值保存,用于与下一个节点比较 。

var isValidBST = function(root) {
    //中序遍历,记录前一个值
    if(!root) return true
    let stack = []
    let pre = -Infinity
    let current = root
    while(stack.length > 0 || current){
        while(current){
            stack.push(current)
            current = current.left
        }
        current = stack.pop()
        if(current.val <= pre){
            return false
        }else{
            pre = current.val
        }
        current = current.right
    }
    return true
};

修剪二叉搜索树

要求是将树的最大值与最小值修剪刀到给定范围内。

注意:如果某个节点不在给定范围内,不是直接砍掉,而是将其下修剪完的接到该节点的位置上!

类递归前序实现,

var trimBST = function(root, L, R) {
    if(!root) return root
    if(root.val > R)  return trimBST(root.left, L, R)
    if(root.val < L)  return trimBST(root.right, L, R)
    root.left = trimBST(root.left, L, R)
    root.right = trimBST(root.right, L, R)
    return root
};

把二叉搜索树转换为累加树

使得每个节点的值是原来的节点值加上所有大于它的节点值之和。

中序遍历是升序遍历的过程,我们需要用到反中序遍历,使得遍历到的值是降序的,同时对值进行累加。

var convertBST = function(root) {
    //使用反中序遍历,右中左 是从大到小的顺序
    let sum = 0
    function help(root){
        if(!root) return root
        help(root.right)
        sum += root.val
        root.val = sum
        help(root.left)
    }
    help(root)
    return root
};