二叉搜索树(BST)

0 阅读2分钟

基础

二叉搜索树(BST)是一种特殊的二叉树,它满足以下性质:

对于任意节点:

  • 左子树中所有节点的值都小于该节点
  • 右子树中所有节点的值都大于该节点
  • 且左右子树本身也都是二叉搜索树

因此,对BST进行中序遍历可以得到一个有序(升序)序列。

“BST为什么查找效率高?”

因为每次比较可以排除一半的搜索范围,类似二分查找,所以平均时间复杂度是O(logN)。

“BST的时间复杂度一定是O(logN)吗?”

不一定。在理想情况下,二叉搜索树是比较平衡的,此时查找、插入、删除的时间复杂度是O(logN),但如果数据插入顺序是有序的(比如递增或递减),BST会退化成一条链表,此时时间复杂度会变成O(N)。

也正是因为普通BST会在最坏情况下性能不稳定,才引出了平衡二叉树(AVL)和红黑树。

实现

注意删除逻辑(难点):

  • 无孩子直接删除
  • 单孩子用子节点替代
  • 双孩子用右子树最小节点替换并递归删除该节点
struct TreeNode
{
    int val;
    TreeNode* left;
    TreeNode* right;

    TreeNode(int v) : val(v), left(nullptr), right(nullptr) {}
};

TreeNode* insert(TreeNode* root, int val)
{
    //tip:一版BST不允许重复值
    //返回值为root
    if (root == nullptr)
    {
        return new TreeNode(val);
    }

    TreeNode* cur = root;
    TreeNode* parent = nullptr;
    while (cur != nullptr)
    {
        parent = cur;
        if (val == cur->val) return root; //不允许重复,直接返回
        else if (val > cur->val) cur = cur->right;
        else cur = cur->left;
    }
    TreeNode* newnode = new TreeNode(val);
    if (val > parent->val) parent->right = newnode;
    else parent->left = newnode;

    return root;
}

TreeNode* getMin(TreeNode* root)
{
    while(root->left != nullptr)
    {
        root = root->left;
    }
    return root;
}

TreeNode* deleteNode(TreeNode* root, int val)
{
    if (root == nullptr) return nullptr;
    
    if (val < root->val)
    {
        root->left = deleteNode(root->left, val);
    }
    else if (val > root->val)
    {
        root->right = deleteNode(root->right, val);
    }
    else
    {
        if (root->left == nullptr && root->right == nullptr)
        {
            //没孩子
            delete root;
            return nullptr;
        }
        else if (root->left == nullptr && root->right != nullptr)
        {
            //有一个孩子
            TreeNode* tmp = root->right;
            delete root;
            return tmp;
        }
        else if (root->left != nullptr && root->right == nullptr)
        {
            TreeNode* tmp = root->left;
            delete root;
            return tmp;
        }
        else
        {
            //有两个孩子 
            TreeNode* minNode = getMin(root->right);
            root->val = minNode->val;
            root->right = deleteNode(root->right, minNode->val);
        }
    }
    return root;
}