#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
#include <climits>
#include <stack>
using namespace std;
typedef int ElemType;
//B-tree结点的结构
typedef struct BNode
{
bool is_leaf;//是否为孩子节点
int size;//当前节点关键字个数
std::vector<ElemType>key;//该节点的关键字
std::vector<BNode*>child;//该节点的孩子节点
}BNode;
typedef struct search_return
{
BNode* node;//所在节点位置
int k;//所在节点第k个关键字
}search_return;
class BTree
{
//private:
public:
BNode* root;//Btree
int t;//B树的度
private:
void split_child(BNode* R,int k);//将R结点k孩子拆分
int merge_child(BNode* R, int k);//合并左右结点
int fix_child(BNode* R, int index);//保证R的k结点关键字个数符合条件
ElemType node_delete(BNode* T, unsigned index);
unsigned node_Insert(BNode* T, ElemType x);
unsigned find_index(BNode* T, ElemType x);
int node_num(BNode* T);//计算该树节点个数
public:
BTree(int degree);
search_return search(ElemType x);
void insert(ElemType x);
void eraser(ElemType x);
int node_rank(ElemType x);//查询x的排名
ElemType search_rank(int rank);//查询排名为rank的关键字
ElemType prev_node(ElemType x);//找到x的前驱节点
ElemType next_node(ElemType x);//找到x的后继节点
void traverse();
};
//B树的初始化
BTree::BTree(int degree)
{
root = new BNode;
root->size = 0;
root->is_leaf = true;
t = degree;
/*
* B树的度为t,t>=2;
* 除根结点外至少t-1个关键字,t个孩子
* 至多含有2t-1个关键字,2t个孩子
*/
}
//查找元素的位置
//search_return BTree::search(ElemType x)
//{
// BNode* curr = root;//从根节点开始
// while (true)
// {
// int index = 0;
// while (index < curr->size)//遍历所在结点关键字
// {
// if (curr->key[index] < x)
// ++index;
// else
// break;
// }
// if (index != curr->size && curr->key[index] == x)
// {
// search_return re;
// re.k = index;
// re.node = curr;
// return re;
// }
// if (curr->is_leaf)
// break;
// curr = curr->child[index];
// }
// search_return re;
// re.k = -1;
// re.node = NULL;
// return re;
//}
//将R结点的k孩子分裂(该孩子结点已满,2t-1个关键字)
void BTree::split_child(BNode* R, int k)
{
BNode* p = R->child[k];//取出该孩子节点
BNode* lNode = new BNode;
BNode* rNode = new BNode;
lNode->is_leaf = p->is_leaf;
lNode->size = this->t - 1;
rNode->is_leaf = p->is_leaf;
rNode->size = this->t - 1;
//将前t-1个关键字放入lNode
for (int i = 0; i < t - 1; ++i)
lNode->key.push_back(p->key[i]);
//取出中间关键字,稍后放入R节点中
int mid_key = p->key[t-1];
//将后t-1个结点放入rNode
for (int i = t; i < 2*t - 1; ++i)
rNode->key.push_back(p->key[i]);
//如果非叶节点,还需要复制孩子节点
if (!p->is_leaf)
{
//将前m个节点放入lNode
for (int i = 0; i < t; ++i)
lNode->child.push_back(p->child[i]);
//将后m个节点放入rNode中
for (int i = t; i < 2 * t; ++i)
rNode->child.push_back(p->child[i]);
}
R->key.push_back(mid_key);//将中间节点加入R
sort(R->key.begin(), R->key.end());//重新非降序排列
++R->size;//关键字个数+1
R->child[k] = lNode;
int n = R->child.size();
R->child.push_back(R->child[n - 1]);
for (int i = n - 1; i >= k + 2; --i)
R->child[i] = R->child[i - 1];
R->child[k + 1] = rNode;
}
//将x关键字插入B树
void BTree::insert(ElemType x)
{
//当根节点满时,拆分需要特别处理
if (root->size == 2 * t - 1)
{
BNode* new_root = new BNode;
new_root->size = 0;
new_root->is_leaf = false;
new_root->child.push_back(root);
root = new_root;
split_child(root, 0);
}
BNode* curr = root;//当前处理的结点,初始时非满
while (!curr->is_leaf)
{
//寻找x应该位于哪个孩子结点
int index = curr->size - 1;
while (index >= 0 && x < curr->key[index])
--index;
++index;
if (curr->child[index]->size == 2 * t - 1)//该孩子节点满
{
split_child(curr, index);
if (curr->key[index] < x)
++index;
}
curr = curr->child[index];
}
curr->key.push_back(x);
sort(curr->key.begin(), curr->key.end());//关键字非降序排列
++curr->size;//关键字+1
}
//新节点2,改变但不是root1,未改变0
//合并R的k结点的左右子节点
int BTree::merge_child(BNode* R, int k)
{
BNode* lchild = R->child[k];
BNode* rchild = R->child[k + 1];
lchild->key.push_back(R->key[k]);//合并R中k关键字
++lchild->size;
for (int i = 0; i < rchild->size; ++i)//合并rchild关键字
lchild->key.push_back(rchild->key[i]);
lchild->size += rchild->size;//调整lchild的关键字数目
node_delete(R, k);
if(!rchild->is_leaf)
for (int i = 0; i <= rchild->size; ++i)//合并rchild的子节点
lchild->child.push_back(rchild->child[i]);
if (!R->size)//如果R结点为空
{
R = lchild;
return 2;
}
return 1;
}
//调整R的index孩子结点大小,同时返回是否调整
int BTree::fix_child(BNode* R, int index)
{
BNode* kid = R->child[index];//定位到所要操作的结点
if (kid->size < t)//如果不符合要求就要进行调整
{
BNode* lkid = R->child[index - 1];//kid左兄弟
BNode* rkid = R->child[index + 1];//kid右兄弟
//向左兄弟节点借
if (index != 0 && lkid->size >= t)
{
node_Insert(kid, R->key[index - 1]);//将R的index-1关键字插入kid中
if(!kid->is_leaf&&!lkid->is_leaf)
kid->child[0] = lkid->child[lkid->size];//将lkid的最有孩子节点放到kid中
R->key[index - 1] = node_delete(lkid, lkid->size - 1);//删除最后一个节点,并赋值给R的index-1
}
//向右兄弟借
else if (index != R->size && rkid->size >= t)
{
node_Insert(kid, R->key[index]);
if (!kid->is_leaf && !rkid->is_leaf)
{
kid->child[kid->size] = rkid->child[0];
rkid->child[0] = rkid->child[1];//删除操作会删除1孩子,所以我们提前将1放在0位置,而0孩子已经被拿走,所以无所谓
}
R->key[index] = node_delete(rkid, 0);
}
//左右兄弟都不够,都是t-1,合并时需要考虑边界
//如果不是第一个元素,结合右兄弟合并
else if (index != 0)//
return merge_child(kid, index - 1);
else
return merge_child(kid, index);
return 1;
}
return 0;
}
//将x关键字删除
void BTree::eraser(ElemType x)
{
BNode* curr = root;//当前处理的节点
while (true)
{
unsigned index = find_index(curr, x);
//在当前结点关键字中找到了x
if (index < curr->size && x == curr->key[index])
{
//如果是叶子节点,直接删除
if (curr->is_leaf)
node_delete(curr, index);
//如果不是叶子节点
else
{
BNode* lkid = curr->child[index];
BNode* rkid = curr->child[index + 1];
//如果左节点关键字多于t-1
//取左节点所在子树最右结点顶替index,然后删除该子树中最右结点
//在查找最右结点的过程,每次调整所在结点大小,保证>=t,这样删除节点时大小合适
if (lkid->size >= t)
{
while (!lkid->is_leaf)
{
fix_child(lkid, lkid->size);//不断调整最右孩子,保证找到最后孩子叶结点时删除可行
lkid = lkid->child[lkid->size];
}
curr->key[index] = node_delete(lkid, lkid->size - 1);//删除结点并给kid的index位置
}
//镜像过程
else if (rkid->size >= t)
{
//找到最左结点,也就是最小节点
while (!rkid->is_leaf)
{
fix_child(rkid, 0);
rkid = rkid->child[0];
}
curr->key[index] = node_delete(rkid, 0);
}
//做有分支结点都只含有t-1个关键字
//合并左右子孩子到左子树
else
{
merge_child(curr, index);
curr = curr->child[index];
continue;
}
}
return;
}
//未在当前结点关键字中找到x
else
{
if (curr->is_leaf)//如果到了叶子节点还没找到
{
std::cout << "no exit!\n";
return;
}
int judge = fix_child(curr, index);
if (judge == 2)
curr = root;
else
curr = curr->child[find_index(curr, x)];
}
}
}
//调试,对节点进行层次遍历
void BTree::traverse()
{
std::queue<BNode*>Q;
Q.push(root);
while (!Q.empty())
{
BNode* tp = Q.front();
Q.pop();
for (int i = 0; i < tp->size; ++i)
std::cout << tp->key[i] << ' ';
//std::cout << tp->is_leaf;
std::cout << std::endl;
int n = tp->child.size();
if(!tp->is_leaf)
for (int i = 0; i < n; ++i)
Q.push(tp->child[i]);
}
}
//删除index位置节点,同时如果非叶子节点index+1孩子节点会删除,调用函数需要提前转移
ElemType BTree::node_delete(BNode* T, unsigned index)
{
ElemType re = T->key[index];
--T->size;
while (index < T->size)//由于size已经-1,所以不会越界
{
T->key[index] = T->key[index + 1];
//如果不是叶子节点还要进行孩子节点的处理
if (!T->is_leaf)
T->child[index + 1] = T->child[index + 2];
++index;
}
T->key.pop_back();//删除关键字
if (!T->is_leaf)
T->child.pop_back();
return re;
}
//将x关键字插入T,并返回插入index,同时如果非叶子节点,index和index+1孩子节点调用函数需要进行调整
unsigned BTree::node_Insert(BNode* T, ElemType x)
{
int index = T->size;//从关键字末尾开始遍历
T->key.push_back(0);//扩展key数组长度
if(!T->is_leaf)
T->child.push_back(NULL);//扩展child数组长度
while (index > 0 && x < T->key[index - 1])
{
T->key[index] = T->key[index - 1];
if(!T->is_leaf)
T->child[index + 1] = T->child[index];
--index;
}
if(!T->is_leaf)
T->child[index + 1] = T->child[index];
T->key[index] = x;
++T->size;
return index;
}
//找到k关键字index,如果未找到,则返回所在孩子节点index
unsigned BTree::find_index(BNode* T, ElemType x)
{
unsigned i = 0;
while (i < T->size && T->key[i] < x)
++i;
return i;
}
//计算T树结点个数
int BTree::node_num(BNode* T)
{
int re = T->size;//当前节点关键字个数
if(!T->is_leaf)
for (int i = 0; i <= T->size; ++i)//孩子节点关键字个数
re += node_num(T->child[i]);
return re;
}
//查询x关键字的排名
int BTree::node_rank(ElemType x)
{
int rank = 0;
BNode* curr = root;
while (true)
{
int index = find_index(curr, x);
if (index != curr->size && x == curr->key[index])//如果找到
{
if (!curr->is_leaf)//如果不是叶子节点需要加上左侧各子树结点个数
for (int i = 0; i <= index; ++i)
rank += node_num(curr->child[i]);
rank += (index + 1);//最后加上当前结点x前关键字个数
return rank;
}
else
{
rank += index;
if (!curr->is_leaf)//如果不是叶子节点还要往下找,同时加上左侧各子树节点个数
{
for (int i = 0; i < index; ++i)
rank += node_num(curr->child[i]);
curr = curr->child[index];
}
else//如果没找到,且已经到了叶子节点,则就是未找到
return 0;
}
}
return rank;
}
//查询排名为rank的关键字
ElemType BTree::search_rank(int rank)
{
BNode* curr = root;//从根节点开始
int curr_rank = 0;
while (true)
{
if (!curr->is_leaf)//如果不是叶子节点
{
for (int i = 0; i <= curr->size; ++i)
{
int temp_rank = rank;
temp_rank += node_num(curr->child[i]);//计算i子树节点个数
++temp_rank;//加上i关键字个数
if (temp_rank == rank)
return curr->key[i];
else if (temp_rank > rank)//如果不是要在i子树中查找,rank不变
curr = curr->child[i];
else
curr_rank = temp_rank;
}
}
else
{
for (int i = 0; i < curr->size; ++i)
{
++curr_rank;
if (curr_rank == rank)
return curr->key[i];
}
}
}
return INT_MAX;//没找到
}
//查询x的前驱结点
ElemType BTree::prev_node(ElemType x)
{
ElemType ans = INT_MIN;
std::queue<BNode*>Q;
Q.push(root);
while (!Q.empty())
{
BNode* tp = Q.front();
Q.pop();
int index = find_index(tp, x);
for (int i = 0; i < index; ++i)
if (tp->key[i]<x && tp->key[i]>ans)
ans = tp->key[i];
//if (index != tp->size && tp->key[index] != x)
if(!tp->is_leaf)
Q.push(tp->child[index]);
}
return ans;
}
ElemType BTree::next_node(ElemType x)
{
ElemType ans = INT_MAX;
std::queue<BNode*>Q;
Q.push(root);
while (!Q.empty())
{
BNode* tp = Q.front();
Q.pop();
int index = find_index(tp, x);
for (int i = index; i < tp->size; ++i)
if (tp->key[i]>x && tp->key[i]<ans)
ans = tp->key[i];
if (!tp->is_leaf)
{
if (index != tp->size && tp->key[index] == x)
Q.push(tp->child[index + 1]);
else
Q.push(tp->child[index]);
}
}
return ans;
}
int main()
{
int n;//操作数
cin >> n;
BTree my_tree(20);
while (n--)
{
int choice, x;
cin >> choice >> x;
switch (choice)
{
case 1:
my_tree.insert(x);
break;
case 2:
my_tree.eraser(x);
break;
case 3:
cout << my_tree.node_rank(x) << endl;
break;
case 4:
cout << my_tree.search_rank(x) << endl;
break;
case 5:
cout << my_tree.prev_node(x) << endl;
break;
case 6:
cout << my_tree.next_node(x) << endl;
break;
default:
break;
}
}
return 0;
}