二叉排序树(BST) 的插入,删除,查询

你需要写一种数据结构,来维护一些数,其中需要提供以下操作:

插入数值 x。
删除数值 x。
输出数值 x 的前驱(前驱定义为现有所有数中小于 x 的最大的数)。
输出数值 x 的后继(后继定义为现有所有数中大于 x 的最小的数)。

题目保证:

操作 1 插入的数值各不相同。
操作 2 删除的数值一定存在。
操作 3 和 4 的结果一定存在。

输入格式
第一行包含整数 n,表示共有 n 个操作命令。
接下来 n 行,每行包含两个整数 opt 和 x,表示操作序号和操作数值。


对于操作 3,4,每行输出一个操作结果。

数据范围
1≤n≤2000,
−10000≤x≤10000

#include<bits/stdc++.h>

using namespace std;

const int INT=1e8;//定义查询前驱和后继时的边界,因为max与min里左子树右子树可能不存在

struct TreeNode
{
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int _val) : val(_val),left(NULL),right(NULL) {}
}*root;
//因为要改变节点的值要加  &引用符号
void insert(TreeNode* &root,int x)
{
    if(root==NULL)//如果为空才新建一个点
    root = new TreeNode(x);
    else if(root->val>x)//如果root的值大于x,插在左子树里
    insert(root->left,x);
    else
    insert(root->right,x);//否则插右子树里
}

void remove(TreeNode* &root,int x)//删除节点,三种情况,是叶节点,有一个左儿子或者右儿子,有左子树且有右子树
{
    if(root==NULL) return;
    if(root->val>x) remove(root->left,x);//如果根节点的值大于x,去左子树删x
    else if(root->val<x) remove(root->right,x);//否则去右子树删除
    else
    {
        if(root->left==NULL&&root->right==NULL)//如果x为叶节点,直接令其为空
            root=NULL;
        else if(root->left==NULL)//如果只有右儿子
            root=root->right;
        else if(root->right==NULL)//如果只有左儿子
            root=root->left;
        else
        {
            auto p = root->left;//当删除的点只有一个左儿子,且左儿子没有右儿子时,删除点的前驱就是roo->left
            while(p->right!=NULL) p = p->right;//如果p还有右儿子,则删除点的前驱就是这个p的右儿子,即p->right
            root->val=p->val;//将前驱的值赋值给要删除点的值
            remove(root->left, p->val);//删除这个前驱
        }
    }
}

int get_pre(TreeNode* root,int x)//输出X的前驱(前驱定义为现有所有数中小于 x 的最大的数)
{
    if(root==NULL)  return -INT;
    if(root->val>=x) return get_pre(root->left,x);//如果根节点的值小大于等于x,则在左子树里去找符合的值
    else
        return max(root->val,get_pre(root->right,x));//如果根节点的值小于x,则小于x的最大值有可能是根节点的值,也有可能是右子树里符合的值
}

int get_suc(TreeNode* root,int x)//输出x的后继(后继定义为现有所有数中大于 x 的最小的数)
{
    if(root==NULL) return INT;//如果根节点为空
    if(root->val<=x) return get_suc(root->right,x);//如果根节点的值小于等于x,则在右子树里去找符合的值
    else 
        return min(root->val,get_suc(root->left,x));//如果根节点的值大于x,则大于x的最小值有可能是根节点的值,也有可能是左子树里符合的值
}


int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        int t,x;
        cin>>t>>x;
        if(t==1) insert(root,x);
        else if(t==2) remove(root,x);
        else if(t==3) cout<<get_pre(root, x)<<endl;
        else cout<<get_suc(root, x)<<endl;
    }
    
    return 0;
}
上一篇:c# – 排序十进制类型的列? (可为空)在WPF DataGrid中


下一篇:二叉排序树的查找 插入 删除