Java刷leetcode总结(五)——二叉查找树(BST)

80 阅读4分钟

二叉搜索树的结构

二叉搜索树是一种特殊的二叉树,它具有以下性质:

  1. 对于任意一个节点,其左子树中所有节点的值都小于它,右子树中所有节点的值都大于它。
  2. 中序遍历二叉搜索树可以得到一个递增的有序序列。

由于二叉搜索树的这些特性,它在查找、插入、删除等操作上都有很高的效率。在查找时,我们可以利用二叉搜索树的有序性进行二分查找,时间复杂度为O(logn);在插入和删除时,我们只需要对树进行简单的旋转和平衡调整即可,时间复杂度也为O(logn)。

二叉搜索树的实现可以使用链表或者数组等数据结构,通常我们使用链表来实现。在Java中,我们可以使用TreeNode类来表示二叉搜索树的节点,该类包含了节点值、左子节点、右子节点等信息。在实现时,需要注意二叉搜索树的节点值不能重复,如果有重复值则需要进行相应处理。

一些常用的操作

  1. 查找操作(递归实现)

二叉搜索树的查找操作可以采用递归的方式实现,其基本思路是:如果当前节点为空或者节点值等于目标值,则返回当前节点;如果目标值小于当前节点的值,则在左子树中查找;否则在右子树中查找。具体代码如下:

public TreeNode searchBST(TreeNode root, int val) {
    if (root == null || root.val == val) {
        return root;
    }
    if (val < root.val) {
        return searchBST(root.left, val);
    } else {
        return searchBST(root.right, val);
    }
}

  1. 插入操作(递归实现)

二叉搜索树的插入操作可以采用递归的方式实现,其基本思路是:如果当前节点为空,则将新节点插入到当前位置;如果目标值小于当前节点的值,则在左子树中插入;否则在右子树中插入。具体代码如下:


public TreeNode insertIntoBST(TreeNode root, int val) {
    if (root == null) {
        return new TreeNode(val);
    }
    if (val < root.val) {
        root.left = insertIntoBST(root.left, val);
    } else {
        root.right = insertIntoBST(root.right, val);
    }
    return root;
}
  1. 删除操作(递归实现)

二叉搜索树的删除操作可以采用递归的方式实现,其基本思路是:如果当前节点为空,则返回空节点;如果目标值小于当前节点的值,则在左子树中删除;如果目标值大于当前节点的值,则在右子树中删除;如果目标值等于当前节点的值,则需要进行具体的删除操作。具体代码如下:

public TreeNode deleteNode(TreeNode root, int key) {
    if (root == null) {
        return null;
    }
    if (key < root.val) {
        root.left = deleteNode(root.left, key);
    } else if (key > root.val) {
        root.right = deleteNode(root.right, key);
    } else {
        if (root.left == null) {
            return root.right;
        } else if (root.right == null) {
            return root.left;
        }
        TreeNode minNode = getMin(root.right);
        root.val = minNode.val;
        root.right = deleteNode(root.right, minNode.val);
    }
    return root;
}

private TreeNode getMin(TreeNode node) {
    while (node.left != null) {
        node = node.left;
    }
    return node;
}

以下是一些常用操作的总结


public class BinarySearchTree {
    
    // 定义二叉搜索树的节点
    private class Node {
        int val;
        Node left;
        Node right;
        
        public Node(int val) {
            this.val = val;
            this.left = null;
            this.right = null;
        }
    }
    
    private Node root; // 根节点
    
    public BinarySearchTree() {
        root = null;
    }
    
    // 查找操作
    public boolean search(int val) {
        Node curr = root;
        while (curr != null) {
            if (curr.val == val) {
                return true;
            } else if (curr.val > val) {
                curr = curr.left;
            } else {
                curr = curr.right;
            }
        }
        return false;
    }
    
    // 插入操作
    public void insert(int val) {
        root = insertNode(root, val);
    }
    
    private Node insertNode(Node node, int val) {
        if (node == null) {
            return new Node(val);
        }
        if (node.val > val) {
            node.left = insertNode(node.left, val);
        } else if (node.val < val) {
            node.right = insertNode(node.right, val);
        }
        return node;
    }
    
    // 删除操作
    public void delete(int val) {
        root = deleteNode(root, val);
    }
    
    private Node deleteNode(Node node, int val) {
        if (node == null) {
            return null;
        }
        if (node.val == val) {
            if (node.left == null) {
                return node.right;
            } else if (node.right == null) {
                return node.left;
            } else {
                Node minNode = getMin(node.right);
                node.val = minNode.val;
                node.right = deleteNode(node.right, minNode.val);
            }
        } else if (node.val > val) {
            node.left = deleteNode(node.left, val);
        } else {
            node.right = deleteNode(node.right, val);
        }
        return node;
    }
    
    // 获取最小节点
    private Node getMin(Node node) {
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }
    
    // 获取最大节点
    private Node getMax(Node node) {
        while (node.right != null) {
            node = node.right;
        }
        return node;
    }
}


做题总结关键词

  1. 中序遍历(Inorder Traversal):一种二叉树的遍历方式,先遍历左子树,再遍历根节点,最后遍历右子树。
  2. 递归(Recursion):一种函数调用自身的编程技巧,常用于解决需要重复执行同样操作的问题。
  3. 迭代(Iteration):一种循环执行的编程结构,与递归相对,通常用于遍历数据结构或执行重复的计算。
  4. 二分查找(Binary Search):一种快速查找有序数组中特定元素的算法。
  5. Morris遍历:一种对二叉树进行遍历的算法,不需要使用递归或者栈,空间复杂度为O(1)。
  6. 旋转(Rotation):一种对二叉搜索树进行平衡的操作,包括左旋和右旋两种方式。
  7. DFS(Depth-First Search):深度优先搜索,是一种遍历图和树的算法,沿着一个路径遍历直到最深处,再回溯到前一个节点继续遍历。
  8. BFS(Breadth-First Search):广度优先搜索,是一种遍历图和树的算法,按照距离从近到远的顺序遍历节点。
  9. 双指针(Two Pointers):一种常用于数组或链表操作的算法技巧,利用两个指针在数组或链表中同时向前或向后移动。
  10. 快速选择(Quick Select):一种基于快速排序的算法,用于在未排序的数组中查找第k小/大的元素。
  11. 动态规划(Dynamic Programming):一种用于解决具有重复子问题和最优子结构性质的问题的算法,通常使用递推式求解。
  12. 分治算法(Divide and Conquer):一种将问题分解为更小子问题的算法,分别解决子问题,最终合并得到原问题的解。