二叉查找树

二叉查找树的基本概念

二叉查找树(Binary Search Tree, BST)是一种特殊的二叉树,满足以下性质:

  • 左子树上所有节点的值小于根节点的值
  • 右子树上所有节点的值大于根节点的值
  • 左右子树也分别为二叉查找树

这种结构使得查找、插入和删除操作的平均时间复杂度为O(log n),最坏情况下为O(n)。

节点定义与初始化

使用整型变量存储节点值,通过数组模拟树结构。定义三个数组:val存储节点值,l存储左子节点索引,r存储右子节点索引,初始时所有值为-1表示空节点。

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 1000;
int val[MAXN], l[MAXN], r[MAXN];
int root = -1, cnt = 0;

插入操作

插入新节点时,从根节点开始比较,小于当前节点则向左子树查找,大于则向右子树查找,直到找到空位置。

void insert(int x) {
    if (root == -1) {
        root = cnt;
        val[cnt] = x;
        cnt++;
        return;
    }
    
    int cur = root;
    while (true) {
        if (x < val[cur]) {
            if (l[cur] == -1) {
                l[cur] = cnt;
                val[cnt] = x;
                cnt++;
                break;
            }
            cur = l[cur];
        } else {
            if (r[cur] == -1) {
                r[cur] = cnt;
                val[cnt] = x;
                cnt++;
                break;
            }
            cur = r[cur];
        }
    }
}

查找操作

查找操作与插入类似,通过比较节点值决定搜索方向,找到返回true,否则返回false。

bool search(int x) {
    int cur = root;
    while (cur != -1) {
        if (x == val[cur]) return true;
        cur = x < val[cur] ? l[cur] : r[cur];
    }
    return false;
}

删除操作

删除操作分为三种情况:

  1. 删除叶子节点:直接移除
  2. 删除有一个子节点的节点:用子节点替代
  3. 删除有两个子节点的节点:用后继节点(右子树的最小值)替代
int find_min(int node) {
    while (l[node] != -1) node = l[node];
    return node;
}

void delete_node(int x) {
    int cur = root, par = -1;
    
    // 查找要删除的节点及其父节点
    while (cur != -1 && val[cur] != x) {
        par = cur;
        cur = x < val[cur] ? l[cur] : r[cur];
    }
    if (cur == -1) return; // 未找到
    
    // 情况1:有两个子节点
    if (l[cur] != -1 && r[cur] != -1) {
        int suc = find_min(r[cur]);
        int tmp = val[suc];
        delete_node(tmp);
        val[cur] = tmp;
        return;
    }
    
    // 情况2和3:有一个或零个子节点
    int child = (l[cur] != -1) ? l[cur] : r[cur];
    if (par == -1) root = child; // 删除的是根节点
    else if (l[par] == cur) l[par] = child;
    else r[par] = child;
}

遍历操作

二叉查找树的中序遍历会产生有序序列。

void inorder(int node) {
    if (node == -1) return;
    inorder(l[node]);
    cout << val[node] << " ";
    inorder(r[node]);
}

示例与测试

以下是一个简单的测试示例:

int main() {
    insert(50);
    insert(30);
    insert(70);
    insert(20);
    insert(40);
    insert(60);
    insert(80);
    
    cout << "Inorder traversal: ";
    inorder(root);
    cout << endl;
    
    cout << "Search 40: " << (search(40) ? "Found" : "Not found") << endl;
    cout << "Search 90: " << (search(90) ? "Found" : "Not found") << endl;
    
    delete_node(20);
    cout << "After deleting 20: ";
    inorder(root);
    cout << endl;
    
    delete_node(30);
    cout << "After deleting 30: ";
    inorder(root);
    cout << endl;
    
    delete_node(50);
    cout << "After deleting 50: ";
    inorder(root);
    cout << endl;
    
    return 0;
}

时间复杂度分析

  • 查找、插入、删除操作的平均时间复杂度为O(log n)
  • 最坏情况下(树退化为链表)时间复杂度为O(n)
  • 中序遍历的时间复杂度为O(n)

平衡二叉查找树

为避免最坏情况,可以使用平衡二叉查找树(如AVL树、红黑树),通过旋转操作保持树的平衡,确保操作时间复杂度为O(log n)。

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值