你需要写一种数据结构,来维护一些数,其中需要提供以下操作:
插入数值 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;
}