二叉搜索树的构造

63 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第20天,点击查看活动详情

5.二叉搜索树的构造

5.1.二叉树搜索树的插入

LeetCode 链接:leetcode.cn/problems/in…

为结点找到最合适的位置,思路比较简单。这里不考虑复杂的左旋右旋。

//递归方式
class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if (root == null) // 如果当前节点为空,也就意味着val找到了合适的位置,此时创建节点直接返回。
            return new TreeNode(val);
            
        if (root.val < val)
            root.right = this.insertIntoBST(root.right, val); // 递归创建右子树
        else if (root.val > val) 
            root.left = this.insertIntoBST(root.left, val); // 递归创建左子树
        
        return root;
    }
}

//迭代方式
class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        TreeNode ans = root;
        if(root == null) return new TreeNode(val);
        while(true){
            if(root.val > val){
                if(root.left != null) root = root.left;
                else {
                    root.left = new TreeNode(val);
                    break;
                }
            } else {
                if(root.right != null) root = root.right;
                else {
                    root.right = new TreeNode(val);
                    break;
                }
            }
        }
        return ans;
    }
}

5.2.删除二叉搜索树的结点

LeetCode 链接:leetcode.cn/problems/de…

删除二叉树的结点比较复杂,有下列五种情况:

没找到删除的节点,遍历到空节点直接返回。

左右子树都为空(叶子节点),直接删除节点, 返回 null 为根节点。

删除节点的左子树为空,右子树不为空,删除节点,右子树补位,返回右子树为根节点。

删除节点的右子树为空,左子树不为空,删除节点,左子树补位,返回左子树为根节点。

左右子树都不为空,则将删除节点的左子树放到删除节点的右子树的最左面节点的左子树上,返回删除节点右子树根节点为新的根节点。

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        if(root == null) return root;

        if(root.val < key) root.right = this.deleteNode(root.right, key);
        else if(root.val > key) root.left = this.deleteNode(root.left, key);
        else {
            if(root.left == null) return root.right;
            if(root.right == null) return root.left;
			//最复杂的情况,需要删除的结点的左右子树均不为空
            TreeNode cur = root.right;
            //找到需要删除的右子树的最左叶子结点
            while (cur.left != null) cur = cur.left;
            //将需要删除的左子树作为上述叶子节点的左子树
            cur.left = root.left;
            //返回需要删除的结点的右子树
            return root.right;
        }
        return root;
    }
}