红黑平衡二叉树及其应用
【问题描述】
一棵红黑树本身就是一棵二叉排序树。红黑树中的结点颜色是黑色或红色。从红黑树的根结点到叶子结点的路径上的黑色结点数目相同,最短的路径就是所有结点都是黑色。根据红黑树的性质,红黑树在平衡类二叉排序树中有许多应用。
【设计要求】
设计红黑平衡二叉树实现动态查找表及其应用。
(1)采用STL红黑平衡二叉树数据结构。
(2)应用基本运算,实现红黑树的简单应用。
(3)C++语言实现。
最终实现功能
因为题目对于功能的描述比较模糊也不清楚允不允许使用C++的__rb_tree所以为了挑战一下选择了手写map,我参考stl的红黑树实现的这个题目。为了表现课设不是全抄stl代码,我想到了洛谷P3369,所以我在红黑树底层增加了node_count属性表示当前子树下节点个数,在实现了基本的stl功能之后,额外实现了logn时间的 get_val函数和get_rank函数。
收获
第一个是友元
stl的标准的map的iterator中有一个属性是 __M_node 这个其实是一个指针,如果对他进行操作的话会很危险,我在发现这一点之后很不理解,认为应该将其封装,于是在完成了基本功能之后,我开始考虑在尽量少改代码的情况下封装,因为在这个整体框架中,iterator和rb_tree是分开的,但是rb_tree必须要访问iterator的 __M_node 这个指针,所以要在屏蔽其他类的情况下只让rb_tree类允许访问,所以想到了友元,因为之前对友元不甚了解,所以花了点时间去学习,不过实现的话并不困难。
第二个是设计的框架
stl设计红黑树选择的是,先定义节点,后实现iterator,最后实现红黑树类,层次还是很分明的。
第三个是一些语法知识
类(类内定义函数,类外定义函数,static函数,operator,深拷贝浅拷贝,构造函数,析构函数,还有typedef,stl的命名规范)
模板(typename)
引用(左值返回,拷贝减少,用函数的返回值来封装)
迭代器(i++,i--,++i,--i,*,==,!=,->(这个的返回值必须是指针))
泛型(实现中使用了不少泛型比如equal之类的,让我熟悉了一下不少函数)
const(这个真的很折磨我,一不小心就会报错):
1.非const类型可以传入const修饰的函数引用参数,但是const修饰类型不能传入未const修饰的函数引用参数,虽然这是可以理解的,会出现:passing *** 什么错误,
2.const修饰的引用可以绑定到临时变量上,比如:const int & a=1。这样便可以减少拷贝。
3.const修饰的类型只能使用const修饰的函数,const修饰的函数也叫只读函数,这个时候相当于你的函数内只能读,不能对原来的属性进行赋值操作,也不能访问非const修饰的函数。
4.const修饰的属性只能在列表初始化中进行初始化,其他任何时候都不能修改。
类型转化还有部分仿函数知识
让我收获了不少之前不怎么使用的语法知识。
第四个是一些代码技巧
一些函数写的在我看来真的不可谓不妙,比如M_erase,M_copy函数,巧妙地用while循环降低了递归深度,之后我也在std::sort函数中看到了类似的写法;再比如调试函数的重要性。
第五个是读代码的能力
之前其实只读过自己的代码,或者学算法的时候大佬注释良好的代码,从来没读过stl这种命名不忍直视,注释只言片语还全是英文的代码,确实是一种挑战,当然之前我学过红黑树,也经常使用map,能够较快地理解设计者的意图,但也很是锻炼。也让我可以方便的阅读其他的stl库代码,能够比较好的理解思想。
分享一下部分有趣的代码片段
while循环降低递归深度
递归深度确实是降低了,建议画图看看。
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
void
Rb_tree<Key,Value,KeyOfValue,Compare>::
M_erase(Link_type x)
//删除子树,这是没有平衡的直接删除,应当只在clear函数中调用。
//很巧妙,用while循环降低了递归深度。
{
//后序遍历,
while(x!=nullptr)
{
M_erase(S_right(x));
Link_type y=S_left(x);
destory_node(x);
x=y;
}
}
迭代器加加操作
但是这里仔细研读会发现,如果树为空,这时 header->left=header->right=header,这时,if语句中的get_min()函数会陷入无限循环(之后给出完整代码),所以我在前面多加入了一句if判断,避免了无限循环,stl库中并没有这句话,而是会像我刚才所说的一样陷入无限循环。
注意:如果迭代器为end(),再加加仍然还是end()
void increment()//迭代器++,需要对end()特判
{
if(M_node->right!=nullptr)
//右孩子不为空,那么直接去左子树的最左偏
{
if(M_node==M_node->right)return;//
M_node=M_node->right;
M_node=rb_tree_node_base::get_min(M_node);
}
else
{
base_ptr M_parent=M_node->parent;
//如果当前节点一直是父节点的右孩子,
//那么需要一直找父亲的父亲,知道当前节点为父亲节点的左孩子,这个
//这个时候父亲节点即下一个
while(M_node==M_parent->right)
M_node=M_parent,M_parent=M_parent->parent;
//特判M_node为根节点的情况,即根节点只有左子树,没有右子树
//这个判断主要是为了end(),
//如果M已经是最右边的节点,那么理应返回end()即header
if(M_node->right!=M_parent)
M_node=M_parent;
}
}
迭代器减减操作
因为减减需要区分header和root,但是这里只有迭代器的几个指针信息,没有其他,所以需要仅凭指针进行区分,header->left指向最左,header->right指向最右,header->parent指向root,而root->parent指向header,所以如果节点的parent->parent=本身,那么这个节点要么是root要么是header,同时我们让header颜色为红,因为root始终为黑,这样就区分了header和root。
还有一点:如果空树,那么在if语句中 M_node->parent->parent会直接报错,因为访问了空指针,我通过特判进行了避免,毕竟只有header的parent有可能为空,不必担心会错判。
注意:对begin()减减会变成end().
void decrement()//迭代器--,需要对begin()特判
{
TODO:嘶,红色说明不是根,那父亲的父亲怎么会是本身呢?
//答:特判header,如果是header,说明当前迭代器是end(),而header是红色的
//那么减去一个就变成了末迭代器。也就是header的右孩子,可以直接返回
if(M_node->parent==nullptr)return;
//所有节点都应该有父亲,但是当树为空且当前为header时不是这样的,对此特判
if(M_node->color==RED&&M_node->parent->parent==M_node)
M_node=M_node->right;
else if(M_node->left!=nullptr)//左孩子不为空
{
if(M_node==M_node->left)return;
M_node=M_node->left;
M_node=rb_tree_node_base::get_max(M_node);
}
else
{
base_ptr M_parent=M_node->parent;
while(M_node==M_parent->left)
M_node=M_parent,M_parent=M_parent->parent;
TODO:为什么--不需要对header特判?
//答:首先header表示end()而不是begin(),
//所以--之后即使变成end()也没有问题,不需要特判
M_node=M_parent;
}
红黑树的insert_unique不重复插入操作
这个函数的主要难点在于我们只有key_compare,因此只能进行小于号比较(这里假设是小于号),没办法使用大于号或者等于号,所以在这个需要判断是否重复的函数中比较麻烦。下面进行了比较详细的注释。
//不允许重复值插入,所以需要进行判断。
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
std::pair<typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator,bool>
Rb_tree<Key,Value,KeyOfValue,Compare>::
insert_unique(const Value&v)
{
Link_type y=this->M_header,x=M_root();
bool comp=true;
while(x!=nullptr)
{
y=x;
comp=M_key_compare(KeyOfValue()(v),S_key(x));
x=comp?S_left(x):S_right(x);
}
iterator j=iterator(y);//j为插入节点的父节点
//true表示插入父亲节点的左边。。
if(comp)
{
//如果j是begin,但v小于j,那么肯定没有重复,直接插入。
if(j==begin())
return std::pair<iterator,bool>(M_insert(x,y,v),true);
else
--j;//移动到了j前一个。为了判断 v 是否已存在:现在已经得出 j > v的结论,如果
//下面出现 j-1 < v的话,那么可以插入,也即v在j和j-1之间;但如果 j-1 >= v,这不合理,说明j-1必然=v,因此拒绝再插入
}
//分析一下:
//1.假设M_key_compare重载的是小于号
//2.x指向nullptr,y指向插入节点的父亲
//3.下面这个if语句继续进行比较的是j和v
//综上
// 经过上面if的处理,现在 j必然<=v,那么如果 j<v,插入即可;如果不是,则说明j==v
if(M_key_compare(KeyOfValue()(*j),KeyOfValue()(v)))
return std::pair<iterator,bool>(M_insert(x,y,v),true);
//上面两个if都没有通过,说明存在相同的节点,返回j(相同的节点),false
return std::pair<iterator,bool>(j,false);
}
自定义的get_val函数
我的要求是,给出排名x,如果x在size()范围内,则给出对应迭代器,否则返回end()。
这段代码写的不是很优美。
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
get_val(size_t x)
{
Link_type y=M_root();
while (y!=nullptr)
{
if( (y->left==nullptr?0:y->left->node_count)+1 == x)
break;
else if( (y->left==nullptr?0:y->left->node_count) >= x)
y=S_left(y);
else
{
x-= (y->left==nullptr?0:y->left->node_count) +1;
y=S_right(y);
}
}
return y==nullptr?end():iterator(y);
}
自定义的get_rank函数
在学习了find函数,upper函数,lower函数之后这个函数就显得游刃有余。
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::size_type
Rb_tree<Key,Value,KeyOfValue,Compare>::
get_rank(const key_type&x)
{
Link_type y=M_root();
size_type rank=1;
while(y!=nullptr)
{
if(!M_key_compare(S_key(y),x))//x<=S_key(y)
y=S_left(y);
else
{
rank+=(y->left==nullptr?0:y->left->node_count)+1;
y=S_right(y);
}
}
return rank;
}
完整的代码
rb_tree代码,map只是对rb_tree进行了再一层封装,并没有太难。
#include <bits/stl_function.h>
#include <bits/stl_pair.h>
#include <bits/allocator.h>
#include <ext/aligned_buffer.h>
#include <bits/stl_construct.h>
//相比于第一版本,在rb_tree_node_base中新增了
// node_count表示当前子树的大小,可以支持log(n)时间 get_val和 get_rank,然后AC洛谷P3369
//以老版本为主,新版本在语法上借鉴吧。
namespace my_rb_tree
{
const bool RED=true;
const bool BLACK=false;
//先对红黑树进行声明,后面友元要用
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
class Rb_tree;
//进行了节点定义,完成了getmin函数和getmax函数,
//是rb_tree_node的父亲
struct rb_tree_node_base
{
typedef rb_tree_node_base* base_ptr;
typedef unsigned long long size_t;
//---const暂时不知道有啥用
typedef const rb_tree_node_base* const_base_ptr;
bool color;
//定义了parent,在iterator中省去了空间。
//也可以在iterator中定义一个栈实现相关功能
base_ptr parent;
base_ptr left;
base_ptr right;
size_t node_count;
rb_tree_node_base():node_count(1){}
TODO:新版C++ stl标准增加了const类型的,暂时不知道有什么用
static base_ptr get_min(base_ptr x)
{
while(x->left!=nullptr)x=x->left;
return x;
}
static base_ptr get_max(base_ptr x)
{
while(x->right!=nullptr)x=x->right;
return x;
}
};
TODO:-------C++新标准用了Key_compare帮助比较,rb_tree_header.之后再看
template <typename Value>
struct rb_tree_node:public rb_tree_node_base
{
typedef rb_tree_node<Value>* Link_type;//指针类型
Value value; //节点值,新标准中用另一种方式存储
rb_tree_node(){this->node_count=1;}
//因为对于const类型不能修改,只能在这里列表初始化。
rb_tree_node(const Value&v):value(v){this->node_count=1;}
};
TODO:这里对齐新版本,删除了父类。
//end()为header,在header中left为begin,right为最右边的,parent指向根
//rb_tree_base_iterator是rb_tree_iterator的父亲
//这里完成了基本的++和--操作
//这下好了,杂糅了老版本和新版本,测。
/*
struct rb_tree_base_iterator
{
//定义指针,距离,双向迭代器
//base_ptr,const_base_ptr在父类中
typedef rb_tree_node_base::base_ptr base_ptr;
base_ptr M_node;
void increment()//迭代器++,需要对end()特判
{
if(M_node->right!=nullptr)
//右孩子不为空,那么直接去左子树的最左偏
{
M_node=M_node->right;
M_node=M_node->get_min(M_node);
}
else
{
base_ptr M_parent=M_node->parent;
//如果当前节点一直是父节点的右孩子,
//那么需要一直找父亲的父亲,知道当前节点为父亲节点的左孩子,这个
//这个时候父亲节点即下一个
while(M_node==M_parent->right)
M_node=M_parent,M_parent=M_parent->parent;
//特判M_node为根节点的情况,即根节点只有左子树,没有右子树
//这个判断主要是为了end(),
//如果M已经是最右边的节点,那么理应返回end()即header
if(M_node->right!=M_parent)
M_node=M_parent;
}
}
void decrement()//迭代器--,需要对begin()特判
{
TODO:嘶,红色说明不是根,那父亲的父亲怎么会是本身呢?
//答:特判header,如果是header,说明当前迭代器是end(),
//那么减去一个就变成了末迭代器。也就是header的右孩子,可以直接返回
if(M_node->color==RED&&M_node->parent->parent==M_node)
M_node=M_node->right;
else if(M_node->left!=nullptr)//左孩子不为空
{
M_node=M_node->left;
M_node=M_node->get_max(M_node);
}
else
{
base_ptr M_parent=M_node->parent;
while(M_node==M_parent->left)
M_node=M_parent,M_parent=M_parent->parent;
TODO:为什么--不需要对header特判?
//答:首先header表示end()而不是begin(),
//所以--之后即使变成end()也没有问题,不需要特判
M_node=M_parent;
}
}
};
*/
//继承rb_tree_base_iterator
//end()为header,在header中left为begin,right为最右边的,parent指向根
//rb_tree_base_iterator是rb_tree_iterator的父亲
//这里完成了基本的++和--操作
//这下好了,杂糅了老版本和新版本,测。
template<typename Value>
struct rb_tree_iterator
{
//base_ptr在父类中,
//定义指针,距离,双向迭代器
typedef Value value_type;
typedef Value& reference;
typedef Value* pointer;
typedef std::bidirectional_iterator_tag iterator_category;
typedef ptrdiff_t difference_type;
typedef rb_tree_iterator<Value> Self;
typedef rb_tree_node_base::base_ptr base_ptr;
typedef rb_tree_node<Value>* Link_type;
protected:
base_ptr M_node;//指针,但是存储的是 rb_tree_node_base的指针,而不是rb_tree_node
//可是 rb_tree_node 是继承与 rb_tree_node_base,每一个rb_tree_node里面都有rb_tree_base_node和value
//所以用指针指向rb_tree_node_base 之后用类型转换可以访问value
//比起第一版本,这里改成了get_M_node函数获取,更加统一。,友元friend
template<typename Key,typename V,typename KeyOfValue,typename Compare>
friend typename Rb_tree<Key,V,KeyOfValue,Compare>::Base_ptr&
Rb_tree<Key,V,KeyOfValue,Compare>::
get_M_node(typename Rb_tree<Key,V,KeyOfValue,Compare>::iterator& p);
public:
rb_tree_iterator() {} //noexcept //noexpect()表示()中如果为true则必然无异常,编译器不会再对其检查
explicit //explicit关键字表示不允许隐性构造
rb_tree_iterator(base_ptr x):M_node(x){}//noexcept
protected:
//对于end如果继续++那么还是end
void increment()//迭代器++,需要对end()特判
{
if(M_node->right!=nullptr)
//右孩子不为空,那么直接去左子树的最左偏
{
if(M_node==M_node->right)return;//
M_node=M_node->right;
M_node=rb_tree_node_base::get_min(M_node);
}
else
{
base_ptr M_parent=M_node->parent;
//如果当前节点一直是父节点的右孩子,
//那么需要一直找父亲的父亲,知道当前节点为父亲节点的左孩子,这个
//这个时候父亲节点即下一个
while(M_node==M_parent->right)
M_node=M_parent,M_parent=M_parent->parent;
//特判M_node为根节点的情况,即根节点只有左子树,没有右子树
//这个判断主要是为了end(),
//如果M已经是最右边的节点,那么理应返回end()即header
if(M_node->right!=M_parent)
M_node=M_parent;
}
}
//begin如果--那么会变成end
void decrement()//迭代器--,需要对begin()特判
{
TODO:嘶,红色说明不是根,那父亲的父亲怎么会是本身呢?
//答:特判header,如果是header,说明当前迭代器是end(),而header是红色的
//那么减去一个就变成了末迭代器。也就是header的右孩子,可以直接返回
if(M_node->parent==nullptr)return;
//所有节点都应该有父亲,但是当树为空且当前为header时不是这样的,对此特判
if(M_node->color==RED&&M_node->parent->parent==M_node)
M_node=M_node->right;
else if(M_node->left!=nullptr)//左孩子不为空
{
if(M_node==M_node->left)return;
M_node=M_node->left;
M_node=rb_tree_node_base::get_max(M_node);
}
else
{
base_ptr M_parent=M_node->parent;
while(M_node==M_parent->left)
M_node=M_parent,M_parent=M_parent->parent;
TODO:为什么--不需要对header特判?
//答:首先header表示end()而不是begin(),
//所以--之后即使变成end()也没有问题,不需要特判
M_node=M_parent;
}
}
public:
//解引用,返回值的引用
reference
operator*()const noexcept//const加在类中函数后面表示这个函数不会修改类中的
//值,如果修改会报错,除非值用Mutable修饰
{
//link_type需要转化成这样才能访问value
return Link_type(M_node)->value;
}
//返回value的指针,先解引用再取址,
TODO:为什么不直接返回this?
//答:pointer指的是value的指针,所以应该返回value的指针
pointer operator->()const noexcept
{
return &(operator*());
}
TODO:-----为什么operator++会有()和(int)两种?-----//
//返回迭代器的引用,这个是 ++it 会返回引用
//operator++()参数为空是这样的。
Self& operator++() noexcept
{
increment();
return *this;//这个地方返回的是迭代器本身
}
//返回迭代器的拷贝,这个是 it++ 不会返回引用,
//返回的是拷贝,operator++()参数为int是这样的
Self operator++(int)noexcept//it++后面不知道为什么会出现一个0
{
Self tmp=*this;
increment();
return tmp;//返回的是迭代器本身的拷贝
}
//和上面的同理。
Self& operator--()noexcept
{
decrement();
return *this;
}
Self operator--(int)noexcept
{
Self tmp=*this;
decrement();
return tmp;
}
//迭代器看的那个operator==有两个参数好像是老版本的。
bool operator==(const Self&other)const noexcept
{
return this->M_node==other.M_node;
}
bool operator!=(const Self&other)const noexcept
{
return this->M_node!=other.M_node;
}
//因为函数和传入的参数无关,所以没有命名
//我超,为什么新版没有这个反而。猜想可能是标准改成了可以直接使用
//struct里面typedef的
// std::bidirectional_iterator_tag iterator_category(const rb_tree_base_iterator&)
// {return std::bidirectional_iterator_tag();}
TODO:这个函数是干啥的?
//是返回指针类型的。
//template<typename Value,typename Ref,typename Ptr>
// inline Value* value_type(const rb_tree_iterator&)
// {
// return (Value*)0;
// //return nullptr;//返回空指针
// }
};
inline void
update_node_count(rb_tree_node_base*x)
{
if(x==nullptr)return;
x->node_count=1;
x->node_count+=(x->left==nullptr?0:x->left->node_count);
x->node_count+=(x->right==nullptr?0:x->right->node_count);
}
//------全局函数,左右旋--------//
//左旋,对x进行左旋,需要传入root作为参数
//左旋,必有右孩子
TODO:为什么这个传入root为引用型
//答:看下面
inline void //内联
rb_tree_rotate_left(rb_tree_node_base*x,rb_tree_node_base*&root)
{
rb_tree_node_base*y=x->right;
x->right=y->left;
if(y->left!=nullptr)
y->left->parent=x;
y->parent=x->parent;
//因为没有传入header,但是却需要,如果x是root的时候修改header的指针
//所以需要对root传入引用
if(x==root)
root=y;
//下面对父亲进行处理
else if(x==x->parent->left)
x->parent->left=y;
else
x->parent->right=y;
y->left=x;
x->parent=y;
update_node_count(x),update_node_count(y);//先更新x在更新y,下面同理
}
//右旋,必有左孩子
inline void
rb_tree_rotate_right(rb_tree_node_base*x,rb_tree_node_base*&root)
{
rb_tree_node_base*y=x->left;
x->left=y->right;
if(y->right!=nullptr)
y->right->parent=x;
y->parent=x->parent;
if(x==root)
root=y;
else if(x==x->parent->right)
x->parent->right=y;
else
x->parent->left=y;
y->right=x;
x->parent=y;
update_node_count(x),update_node_count(y);
}
//---------全局函数,红黑树的Rebalance,解决双红和双黑问题------//
//方法论:插入节点站在祖父,删除节点站在父亲
inline void
rb_tree_rebalance_for_insert(rb_tree_node_base*x,rb_tree_node_base*&root)
{
//x指向新插入的节点,新节点为红色
//同时x永远指向红色的节点。
x->color=RED;
rb_tree_node_base*parent=x->parent,*grandparent=parent->parent,*y;
//站在祖父考虑问题。
while(x!=root&&parent->color==RED)
{
update_node_count(parent);
//左型
if(parent==grandparent->left)
{
y=grandparent->right;
//两个孩子都是红色,
//策略:本节点染红,两个孩子染黑,则满足性质
if(y!=nullptr&&y->color==RED)
{
parent->color=BLACK;
y->color=BLACK;
grandparent->color=RED;
x=grandparent;
//需要继续检查
update_node_count(x);
}
//左双红
//策略:分两种LL红和LR红,LR红需要先左旋
//然后,孩子染黑,父亲染红,
else
{
//LR型,先左旋
//这代码正确吗?
//if里面x=x->parent这个时候x的位置改变了啊,变成了父亲,抱歉,不该质疑
//左旋之前,x先移动到父亲,左旋之后x的位置又降下来了。
//所以每次旋转之后parent,grandparent都需要修改
if(x==parent->right)
{
x=parent;
rb_tree_rotate_left(x,root);
parent=x->parent;//需要刷新
grandparent=parent->parent;
}
parent->color=BLACK;//父亲染黑,祖父染红
grandparent->color=RED;
rb_tree_rotate_right(grandparent,root);//这个时候右旋,循环结束
//还得是stl,rebalance代码比我的简短多了。
}
}
else
{
y=grandparent->left;
if(y!=nullptr&&y->color==RED)
{
y->color=parent->color=BLACK;
grandparent->color=RED;
x=grandparent;
update_node_count(x);
}
else
{
if(x==parent->left)
{
x=parent;
rb_tree_rotate_right(x,root);
parent=x->parent;//需要刷新
grandparent=parent->parent;
}
parent->color=BLACK;
grandparent->color=RED;
rb_tree_rotate_left(grandparent,root);
}
}
//应该放在while循环在下面,
parent=x->parent;
grandparent=parent->parent;
}
while(parent!=root)
update_node_count(parent),parent=parent->parent;
update_node_count(root);
root->color=BLACK;
}
//站在父亲节点
TODO:leftmost?rightmost?
inline rb_tree_node_base*
rb_tree_rebalance_for_erase(rb_tree_node_base*z,
rb_tree_node_base*&root,
rb_tree_node_base*&leftmost,
rb_tree_node_base*&rightmost)
{
TODO:x为什么始终指向空?x是干啥的啊?
rb_tree_node_base*y=z,*x=nullptr,*x_parent=nullptr;
//作用,让y指向被删除节点,x指向被删除节点的继任节点。
//x_parent指向删除y之后的x的父亲,之所以不直接 x->parent是因为x可能为空
if(y->left==nullptr)
x=y->right;
else if(y->right==nullptr)
x=y->left;
else
{
y=y->right;//需要直接后继;
y=rb_tree_node_base::get_min(y);
x=y->right;
}
//p=y;//指向后继。
TODO:老版本没有move函数,所以没有进行值替代,而是进行的指针替代
//这里为了方便进行值替代
//然而我想多了,如果想要值替代,需要传入的是rb_tree_node而不是rb_tree_node_base
//下面做的是把用y把z指针替代,同时用x把y指针替代。
if(y!=z)//y是z的后继,注意,这个时候z的左节点必然不是y但是右节点可能是,需要讨论
{
z->left->parent=y;
y->left=z->left;
if(y!=z->right) //对y不是z的右节点特判
{
x_parent=y->parent;//x_parent
if(x!=nullptr)x->parent=y->parent;
y->parent->left=x;//y一定在父亲的左边,因为是后继
y->right=z->right;
z->right->parent=y;
}
else
x_parent=y;
//把z摘下来,y放上去。
if(root==z)
root=y;
else if(z->parent->left==z)
z->parent->left=y;
else
z->parent->right=y;
y->parent=z->parent;
std::swap(y->color,z->color);
y=z;
// __y now points to node to be actually deleted
}
else //z本身就只剩一个孩子,所以y==z
{
x_parent=y->parent;
if(x!=nullptr)x->parent=y->parent;
if(root==z)
root=x;
else if(z->parent->left==z)
z->parent->left=x;
else
z->parent->right=x;
if(leftmost==z)
{
if(z->right==nullptr)
leftmost=z->parent;
else
leftmost=rb_tree_node_base::get_min(x);
}
if(rightmost==z)
{
if(z->left==nullptr)
rightmost=z->parent;
else
rightmost=rb_tree_node_base::get_max(x);
}
}
if(y->color==BLACK)//如果删除的是黑色节点,这个时候处理双黑问题
{
rb_tree_node_base*brother;//指向x的兄弟
while(x!=root&&(x==nullptr||x->color==BLACK))
{
update_node_count(x_parent);//应该更新父亲,因为x可能为空,而且x也不需要
if(x==x_parent->left)
{
brother=x_parent->right;
//右兄弟有红,这个时候有以下条件:
//1.父亲为黑 2.右兄弟必有两个黑色孩子
//3.右兄弟的两个黑色孩子可能还有红色孩子
//策略:兄弟染黑,父亲染红,父亲左旋
//这个时候x,x_parent相对位置没有变,
//但是x_parent变成了红色,问题转化
if(brother->color==RED)
{
brother->color=BLACK;
x_parent->color=RED;
rb_tree_rotate_left(x_parent,root);
brother=x_parent->right;
}
//兄弟为黑,且孩子双黑,这个时候需要进一步调整,进入下一次循环。
//因为删去的节点为黑色,可以知道,左子树比右子树少了一个黑色路径。
if((brother->left==nullptr||brother->left->color==BLACK)&&
(brother->right==nullptr||brother->right->color==BLACK))
{
//如果父亲为红色,那么这里可能会出现双红现象。在while循环最下面进行了处理。
//还以为没有考虑父亲为红色呢,不该质疑
brother->color=RED;
x=x_parent;
x_parent=x_parent->parent;
}
else//兄弟为黑,且至少有一个红孩子
{
if(brother->right==nullptr||brother->right->color==BLACK)
{
TODO:这个判断是必要的吗?
//左节点应该必然存在并且是红色的啊
if(brother->left!=nullptr)
brother->left->color=BLACK;
//RL型红色,先右旋
brother->color=RED;
rb_tree_rotate_right(brother,root);
brother=x_parent->right;
}
brother->color=x_parent->color;
x_parent->color=BLACK;
//这里也不应该啊,这里应该必然为红色啊。
if(brother->right!=nullptr)
brother->right->color=BLACK;
rb_tree_rotate_left(x_parent,root);
break;
}
}
else
{
brother=x_parent->left;
if(brother->color==RED)
{
brother->color=BLACK;
x_parent->color=RED;
rb_tree_rotate_right(x_parent,root);
brother=x_parent->left;
}
if((brother->right==nullptr||brother->right->color==BLACK)&&
(brother->left==nullptr||brother->left->color==BLACK))
{
brother->color=RED;
x=x_parent;
x_parent=x_parent->parent;
}
else
{
if(brother->left==nullptr||brother->left->color==BLACK)
{
if(brother->right!=nullptr)
brother->right->color=BLACK;
brother->color=RED;
rb_tree_rotate_left(brother,root);//之前弄错了,写成了right
brother=x_parent->left;
}
brother->color=x_parent->color;
x_parent->color=BLACK;
if(brother->left!=nullptr)
brother->left->color=BLACK;
rb_tree_rotate_right(x_parent,root);
break;
}
}
}
if(x!=nullptr)x->color=BLACK;//应该放在while外面,可以排除继任节点是红色
}
while(x_parent!=root)
update_node_count(x_parent),x_parent=x_parent->parent;
update_node_count(root);
return y;//返回y,y是待删除节点,这个应该是来删除的(为什么不直接在这里删除?)
}
//正活开始。
template<typename Value>
struct rb_tree_base
{
rb_tree_base():M_header(nullptr){M_header=new rb_tree_node<Value>;}
~rb_tree_base(){M_put_node(M_header);}
protected:
rb_tree_node<Value>* M_header;//头指针
rb_tree_node<Value>* M_get_node(const Value &v)
{
rb_tree_node<Value>*tmp=new rb_tree_node<Value>(v);
tmp->left=tmp->right=tmp->parent=nullptr;
tmp->color=RED;
return tmp;
}
void M_put_node(rb_tree_node<Value>*p)
{
delete p;
}
};
//KeyOfValue是仿函数,用于取出需要比较的值
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
class Rb_tree:protected rb_tree_base<Value> //继承于rb_tree_base,天生有一个初始化好的头结点。
{
typedef rb_tree_base<Value> Base;
typedef Rb_tree<Key,Value,KeyOfValue,Compare> RB_Self;
protected:
typedef rb_tree_node_base* Base_ptr;
typedef rb_tree_node<Value> Rb_tree_node;
public:
typedef Key key_type;
typedef Value value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef Rb_tree_node* Link_type;
typedef unsigned long long size_type;
typedef std::ptrdiff_t difference_type;
protected:
//rb_tree_node<Value>* M_header;
Link_type M_create_node(const value_type& x)
{
Link_type tmp=this->M_get_node(x);
return tmp;
}
Link_type M_clone_node(Link_type x)
{
Link_type tmp=new Rb_tree_node(x->value);
tmp->color=x->color;
tmp->left=tmp->right=nullptr;
return tmp;
}
void destory_node(Link_type p)
{
//Destproy就是调用析构函数,对于new出来的则delete
std::_Destroy(&p->value);
this->M_put_node(p);
}
protected:
size_type M_node_count;
Compare M_key_compare;
Link_type& M_root()const{
return (Link_type&) this->M_header->parent;
}
Link_type& M_leftmost()const{
return (Link_type&) this->M_header->left;
}
Link_type& M_rightmost()const{
return (Link_type&) this->M_header->right;
}
static Link_type& S_left(Link_type x){
return (Link_type&)(x->left);
}
static Link_type& S_right(Link_type x){
return (Link_type&)(x->right);
}
static Link_type& S_parent(Link_type x){
return (Link_type&)(x->parent);
}
static reference S_value(Link_type x){
return x->value;
}
static const Key& S_key(Link_type x){
return KeyOfValue()(S_value(x));
}
// static bool& S_color(Link_type x){
// return (bool&)(x->color);
// }
static Link_type& S_left(Base_ptr __x)
{ return (Link_type&)(__x->left); }
static Link_type& S_right(Base_ptr __x)
{ return (Link_type&)(__x->right); }
static Link_type& S_parent(Base_ptr __x)
{ return (Link_type&)(__x->parent); }
static reference S_value(Base_ptr __x)
{ return ((Link_type)__x)->value; }
static const Key& S_key(Base_ptr __x)
{ return KeyOfValue()(S_value(Link_type(__x)));}
static bool& S_color(Base_ptr __x)
{ return (bool&)(Link_type(__x)->color); }
static Link_type S_minimum(Link_type __x)
{ return (Link_type) rb_tree_node_base::get_min(__x); }
static Link_type S_maximum(Link_type __x)
{ return (Link_type) rb_tree_node_base::get_max(__x); }
public:
typedef rb_tree_iterator<value_type> iterator;
private:
iterator M_insert(Base_ptr x,Base_ptr y,const value_type& v);
Link_type M_copy(Link_type x,Link_type p);
void M_erase(Link_type x);
Base_ptr& get_M_node(iterator& p)
{return p.M_node;}
public:
Rb_tree():
M_node_count(0),M_key_compare()
{M_empty_initilaize();}
Rb_tree(const Compare&comp):
M_node_count(0),M_key_compare(comp)
{M_empty_initilaize();}
//也是深拷贝
TODO:
Rb_tree(const RB_Self&x):
M_node_count(0),M_key_compare(x.M_key_compare)
{
if(x.M_root()==nullptr)
M_empty_initilaize();
else
{
S_color(this->M_header)=RED;
M_root()=M_copy(x.M_root(),this->M_header);
M_leftmost()=S_minimum(M_root());
M_rightmost()=S_maximum(M_root());
}
M_node_count=x.M_node_count;
}
~Rb_tree(){clear();}
//深拷贝
RB_Self& operator=(const RB_Self&x);
private:
void M_empty_initilaize()
{
//M_header->color=RED;
S_color(this->M_header)=RED;
M_root()=nullptr;
M_leftmost()=this->M_header;
M_rightmost()=this->M_header;
}
public:
Compare key_comp() const {return M_key_compare;}
iterator begin() const{return iterator(M_leftmost());}
iterator end() const {return iterator(this->M_header);}
bool empty()const {return M_node_count==0;}
size_type size()const {return M_node_count;}
size_type max_size() const{return size_type(-1);}
//只需要换header,count和compare
void swap(RB_Self&t)
{
std::swap(this->M_header,t.M_header);
std::swap(M_node_count,t.M_node_count);
std::swap(M_key_compare,t.M_key_compare);
}
public:
std::pair<iterator,bool> insert_unique(const value_type&x);
iterator insert_equal(const value_type&x);
//将x插入rb,保持节点独一无二
iterator insert_unique(iterator position,const value_type&x);
//允许节点重复
iterator insert_equal(iterator position,const value_type&x);
//这里和新保持一致,erase之后应该返回下一个迭代器
iterator erase(iterator position);
size_type erase(const key_type&x);
iterator erase(iterator first,iterator last);
void clear()
{
if(M_node_count>0)
{
M_erase(M_root());
M_leftmost()=this->M_header;
M_rightmost()=this->M_header;
M_root()=nullptr;
M_node_count=0;
}
}
public:
iterator find(const key_type&x);
size_type count(const key_type&x);
iterator lower_bound(const key_type&x);
iterator upper_bound(const key_type&x);
//由值获得排名
size_type get_rank(const key_type&x);
//由排名获得值(迭代器)
iterator get_val(size_t x);
std::pair<iterator,iterator> equal_range(const key_type&x);
bool __rb_verify();//debugging
//这个放在里面,后面一个放在里面,
bool operator==(const RB_Self&x)const
{
return size()==x.size()&&
std::equal(begin(),end(),x.begin());
}
};
//类外定义函数::::方法
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::RB_Self&
Rb_tree<Key,Value,KeyOfValue,Compare>
::operator=(const RB_Self&x)
{
if(this!=&x)
{
clear();
M_node_count=0;
M_key_compare=x.M_key_compare;
if(x.M_root()==nullptr)
{
M_root()=nullptr;
M_leftmost()=this->M_header;
M_rightmost()=this->M_header;
}
else
{
M_root()=M_copy(x.M_root(),this->M_header);
M_leftmost()=S_minimum(M_root());
M_rightmost()=S_maximum(M_root());
M_node_count=x.M_node_count;
}
}
return *this;
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
M_insert(Base_ptr a,Base_ptr b,const value_type & v)
{
//x是新值插入点,y是x的父节点,v是插入值,z是新节点。
Link_type x=(Link_type)a,y=(Link_type)b,z=nullptr;
if(y==this->M_header||x!=nullptr||
M_key_compare(KeyOfValue()(v),S_key(y)))
{
z=M_create_node(v);
S_left(y)=z;
if(y==this->M_header)
{
M_root()=z;
M_rightmost()=z;
}
else if(y==M_leftmost())
{
M_leftmost()=z;
}
}
else
{
z=M_create_node(v);
S_right(y)=z;
if(y==M_rightmost())
M_rightmost()=z;
}
S_parent(z)=y;
S_left(z)=S_right(z)=nullptr;
rb_tree_rebalance_for_insert(z,this->M_header->parent);
++M_node_count;
return iterator(z);
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
void
Rb_tree<Key,Value,KeyOfValue,Compare>::
M_erase(Link_type x)
//删除子树,这是没有平衡的直接删除,应当只在clear函数中调用。
//很巧妙,用while循环降低了递归深度。
{
//后序遍历,
while(x!=nullptr)
{
M_erase(S_right(x));
Link_type y=S_left(x);
destory_node(x);
x=y;
}
}
//允许重复值插入。
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
insert_equal(const Value&v)
//我怎么记得新版本这里是直接用的lower_bound
{
Link_type y=this->M_header,x=M_root();
while(x!=nullptr)
{
y=x;
x=M_key_compare(KeyOfValue()(v),S_key(x))?
S_left(x):S_right(x);
}
return M_insert(x,y,v);
}
//不允许重复值插入,所以需要进行判断。
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
std::pair<typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator,bool>
Rb_tree<Key,Value,KeyOfValue,Compare>::
insert_unique(const Value&v)
{
Link_type y=this->M_header,x=M_root();
bool comp=true;
while(x!=nullptr)
{
y=x;
comp=M_key_compare(KeyOfValue()(v),S_key(x));
x=comp?S_left(x):S_right(x);
}
iterator j=iterator(y);//j为插入节点的父节点
//true表示插入父亲节点的左边。。
if(comp)
{
//如果j是begin,但v小于j,那么肯定没有重复,直接插入。
if(j==begin())
return std::pair<iterator,bool>(M_insert(x,y,v),true);
else
--j;//移动到了j前一个。为了判断 v 是否已存在:现在已经得出 j > v的结论,如果
//下面出现 j-1 < v的话,那么可以插入,也即v在j和j-1之间;但如果 j-1 >= v,这不合理,说明j-1必然=v,因此拒绝再插入
}
//分析一下:
//1.假设M_key_compare重载的是小于号
//2.x指向nullptr,y指向插入节点的父亲
//3.下面这个if语句继续进行比较的是j和v
//综上
// 经过上面if的处理,现在 j必然<=v,那么如果 j<v,插入即可;如果不是,则说明j==v
if(M_key_compare(KeyOfValue()(*j),KeyOfValue()(v)))
return std::pair<iterator,bool>(M_insert(x,y,v),true);
//上面两个if都没有通过,说明存在相同的节点,返回j(相同的节点),false
return std::pair<iterator,bool>(j,false);
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
insert_unique(iterator position,const Value&v)
{
if(get_M_node(position)==this->M_header->left)//begin()
{
if(size()>0&&
M_key_compare(KeyOfValue()(v),S_key(get_M_node(position))))
{
return M_insert(get_M_node(position),get_M_node(position),v);
}
else
return insert_unique(v).first;
}
else if(get_M_node(position)==this->M_header)
{
if(M_key_compare(S_key(M_rightmost()),KeyOfValue()(v)))
{
return M_insert(nullptr,M_rightmost(),v);
}
else
return insert_unique(v).first;
}
else
{
iterator before=position;
--before;
//在before和position之间
if(M_key_compare(S_key(get_M_node(before)),KeyOfValue()(v))&&
M_key_compare(KeyOfValue()(v),S_key(get_M_node(position))))
{
if(S_right(get_M_node(before))==nullptr)
return M_insert(nullptr,get_M_node(before),v);
else
return M_insert(get_M_node(position),get_M_node(position),v);
}
else
return insert_unique(v).first;
}
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
insert_equal(iterator position,const Value&v)
{
if(get_M_node(position)==this->M_header->left)
{
if(size()>0&&//position不大于v
!M_key_compare(S_key(get_M_node(position)),KeyOfValue()(v)))
return M_insert(get_M_node(position),get_M_node(position),v);
else
return insert_equal(v);
}
else if(get_M_node(position)==this->M_header)
{
if(!M_key_compare(KeyOfValue()(v),S_key(M_rightmost())))
return M_insert(nullptr,M_rightmost(),v);
else
return insert_equal(v);
}
else
{
iterator before=position;
--before;
if(!M_key_compare(KeyOfValue()(v),S_key(get_M_node(before)))&&
!M_key_compare(S_key(get_M_node(position)),KeyOfValue()(v)))
if(S_right(get_M_node(before))==nullptr)
return M_insert(nullptr,get_M_node(before),v);
else
return M_insert(get_M_node(position),get_M_node(position),v);
else
return insert_equal(v);
}
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
erase(iterator position)
{
if(position==end())return end();
iterator successor=position;
++successor;
rb_tree_node_base* y=rb_tree_rebalance_for_erase(
get_M_node(position),
this->M_header->parent,
this->M_header->left,
this->M_header->right
);
destory_node((Link_type)y);
--M_node_count;
return successor;
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::size_type
Rb_tree<Key,Value,KeyOfValue,Compare>::
erase(const Key&x)
{
std::pair<iterator,iterator> p=equal_range(x);
size_type n=count(x);
erase(p.first,p.second);
return n;
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::Link_type
Rb_tree<Key,Value,KeyOfValue,Compare>::
M_copy(Link_type x,Link_type p)//拷贝一个子树。使用递归算法。但是也使用了while降低了递归深度。
{
Link_type top=M_clone_node(x);
top->parent=p;
try
{
if(x->right!=nullptr)
top->right=M_copy(S_right(x),top);//递归
p=top;
x=S_left(x);
while(x!=nullptr)
{
Link_type y=M_clone_node(x);
p->left=y;
y->parent=p;
if(x->right!=nullptr)
y->right=M_copy(S_right(x),y);
p=y;
x=S_left(x);
}
}
catch(...)
{
M_erase(top);
throw;
}
return top;
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
erase(iterator first,iterator last)
{
if(first==begin()&&last==end())
{
clear();
return end();
}
else
{
while(first!=last)
erase(first++);
return last;
}
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
find(const key_type&k)
{
Link_type y=this->M_header,x=M_root();//y是last node while is not less than k
//y指向x的下一个迭代器
while(x!=nullptr)
//如果x>=k就向左,同时为了保持y是x下一个迭代器,y刷新
//为什么不M_key_compare(k,x)?因为那样的话是 > 而我们需要的是 >=
if(!M_key_compare(S_key(x),k))
y=x,x=S_left(x);
else
x=S_right(x);
iterator j=iterator(y);
//j如果是end,显然直接返回end,
//所求j应该>=k,如果k<j取真,说明 j>k 不存在k这个节点。。。。
return (j==end()||M_key_compare(k,KeyOfValue()(*j)))?
end():j;
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::size_type
Rb_tree<Key,Value,KeyOfValue,Compare>::
count(const Key&k)
{
std::pair<iterator,iterator> p=equal_range(k);
return std::distance(p.first,p.second);
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
lower_bound(const Key&k)
{
Link_type y=this->M_header,x=M_root();
//这部分和find一致
while(x!=nullptr)
if(!M_key_compare(S_key(x),k))
y=x,x=S_left(x);
else
x=S_right(x);
return iterator(y);
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
upper_bound(const Key&k)
{
Link_type y=this->M_header,x=M_root();
//改成了M_key_compare(k,S_key(x))而已
while(x!=nullptr)
if(M_key_compare(k,S_key(x)))
y=x,x=S_left(x);
else
x=S_right(x);
return iterator(y);
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
get_val(size_t x)
{
Link_type y=M_root();
while (y!=nullptr)
{
if( (y->left==nullptr?0:y->left->node_count)+1 == x)
break;
else if( (y->left==nullptr?0:y->left->node_count) >= x)
y=S_left(y);
else
{
x-= (y->left==nullptr?0:y->left->node_count) +1;
y=S_right(y);
}
}
return y==nullptr?end():iterator(y);
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::size_type
Rb_tree<Key,Value,KeyOfValue,Compare>::
get_rank(const key_type&x)
{
Link_type y=M_root();
size_type rank=1;
while(y!=nullptr)
{
if(!M_key_compare(S_key(y),x))//x<=S_key(y)
y=S_left(y);
else
{
rank+=(y->left==nullptr?0:y->left->node_count)+1;
y=S_right(y);
}
}
return rank;
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
std::pair<typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator,typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator>
Rb_tree<Key,Value,KeyOfValue,Compare>::
equal_range(const Key&k)
{
return std::pair<iterator,iterator>(lower_bound(k),upper_bound(k));
}
inline int black_count(rb_tree_node_base*node,rb_tree_node_base*root)
{
if(node==0)
return 0;
else
{
int bc=node->color==BLACK?1:0;
if(node==root)
return bc;
else
return bc+black_count(node->parent,root);
}
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
bool
Rb_tree<Key,Value,KeyOfValue,Compare>::
__rb_verify()
{
if(M_node_count==0||begin()==end())
return M_node_count==0&&begin()==end()&&
this->M_header->M_left==this->M_header&&this->M_header->M_right==this->M_header;
int len=black_count(M_leftmost(),M_root());
for(iterator it=begin();it!=end();++it)
{
Link_type x=(Link_type)it.M_node;
Link_type L=S_left(x);
Link_type R=S_right(x);
if(x->color==RED&&((L!=nullptr&&L->color==RED)||
(R!=nullptr&&R->color==RED)))
return false;
if(L!=nullptr&&M_key_compare(S_key(x),S_key(L)))
return false;
if(R!=nullptr&&M_key_compare(S_key(R),S_key(x)))
return false;
if(L==nullptr&&R==nullptr&&black_count(x,M_root())!=len)
return false;
}
if(M_leftmost()!=rb_tree_node_base::get_min(M_root()))
return false;
if(M_rightmost()!=rb_tree_node_base::get_max(M_root()))
return false;
return true;
}
template<typename Key,typename Value,typename KeyofValue,typename Compare>
struct rb_tree:public Rb_tree<Key,Value,KeyofValue,Compare>
{
typedef Rb_tree<Key,Value,KeyofValue,Compare> Base;
rb_tree(const Compare&comp=Compare()) :Base(comp){}
~rb_tree(){}
};
}
利用所写红黑树AC洛谷P3369
复制粘贴即可AC。
//使用由rb_treeV2.0封装而成的multimap,通过get_val和get_rank函数,通过洛谷P3369 普通平衡树
//https://www.luogu.com.cn/problem/P3369
#include <iostream>
#include <bits/stl_construct.h>
#include <bits/stl_function.h>
#include <bits/stl_pair.h>
#include <bits/allocator.h>
#include <ext/aligned_buffer.h>
//以老版本为主,新版本在语法上借鉴吧。
namespace my_rb_tree
{
const bool RED=true;
const bool BLACK=false;
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
class Rb_tree;
//进行了节点定义,完成了getmin函数和getmax函数,
//是rb_tree_node的父亲
struct rb_tree_node_base
{
typedef rb_tree_node_base* base_ptr;
typedef unsigned long long size_t;
//---const暂时不知道有啥用
typedef const rb_tree_node_base* const_base_ptr;
bool color;
//定义了parent,在iterator中省去了空间。
//也可以在iterator中定义一个栈实现相关功能
base_ptr parent;
base_ptr left;
base_ptr right;
size_t node_count;
rb_tree_node_base():node_count(1){}
TODO:新版C++stl标准增加了const类型的,暂时不知道有什么用
static base_ptr get_min(base_ptr x)
{
while(x->left!=nullptr)x=x->left;
return x;
}
static base_ptr get_max(base_ptr x)
{
while(x->right!=nullptr)x=x->right;
return x;
}
};
TODO:-------C++新标准用了Key_compare帮助比较,rb_tree_header.之后再看
template <typename Value>
struct rb_tree_node:public rb_tree_node_base
{
typedef rb_tree_node<Value>* Link_type;//指针类型
Value value; //节点值,新标准中用另一种方式存储
rb_tree_node(){this->node_count=1;}
rb_tree_node(const Value&v):value(v){this->node_count=1;}
};
TODO:这里对齐新版本,删除了父类。
//end()为header,在header中left为begin,right为最右边的,parent指向根
//rb_tree_base_iterator是rb_tree_iterator的父亲
//这里完成了基本的++和--操作
//这下好了,杂糅了老版本和新版本,测。
/*
struct rb_tree_base_iterator
{
//定义指针,距离,双向迭代器
//base_ptr,const_base_ptr在父类中
typedef rb_tree_node_base::base_ptr base_ptr;
base_ptr M_node;
void increment()//迭代器++,需要对end()特判
{
if(M_node->right!=nullptr)
//右孩子不为空,那么直接去左子树的最左偏
{
M_node=M_node->right;
M_node=M_node->get_min(M_node);
}
else
{
base_ptr M_parent=M_node->parent;
//如果当前节点一直是父节点的右孩子,
//那么需要一直找父亲的父亲,知道当前节点为父亲节点的左孩子,这个
//这个时候父亲节点即下一个
while(M_node==M_parent->right)
M_node=M_parent,M_parent=M_parent->parent;
//特判M_node为根节点的情况,即根节点只有左子树,没有右子树
//这个判断主要是为了end(),
//如果M已经是最右边的节点,那么理应返回end()即header
if(M_node->right!=M_parent)
M_node=M_parent;
}
}
void decrement()//迭代器--,需要对begin()特判
{
TODO:嘶,红色说明不是根,那父亲的父亲怎么会是本身呢?
//答:特判header,如果是header,说明当前迭代器是end(),
//那么减去一个就变成了末迭代器。也就是header的右孩子,可以直接返回
if(M_node->color==RED&&M_node->parent->parent==M_node)
M_node=M_node->right;
else if(M_node->left!=nullptr)//左孩子不为空
{
M_node=M_node->left;
M_node=M_node->get_max(M_node);
}
else
{
base_ptr M_parent=M_node->parent;
while(M_node==M_parent->left)
M_node=M_parent,M_parent=M_parent->parent;
TODO:为什么--不需要对header特判?
//答:首先header表示end()而不是begin(),
//所以--之后即使变成end()也没有问题,不需要特判
M_node=M_parent;
}
}
};
*/
//继承rb_tree_base_iterator
//end()为header,在header中left为begin,right为最右边的,parent指向根
//rb_tree_base_iterator是rb_tree_iterator的父亲
//这里完成了基本的++和--操作
//这下好了,杂糅了老版本和新版本,测。
template<typename Value>
struct rb_tree_iterator
{
//base_ptr在父类中,
//定义指针,距离,双向迭代器
typedef Value value_type;
typedef Value& reference;
typedef Value* pointer;
typedef std::bidirectional_iterator_tag iterator_category;
typedef ptrdiff_t difference_type;
typedef rb_tree_iterator<Value> Self;
typedef rb_tree_node_base::base_ptr base_ptr;
typedef rb_tree_node<Value>* Link_type;
protected:
base_ptr M_node;//指针
template<typename Key,typename V,typename KeyOfValue,typename Compare>
friend typename Rb_tree<Key,V,KeyOfValue,Compare>::Base_ptr&
Rb_tree<Key,V,KeyOfValue,Compare>::
get_M_node(typename Rb_tree<Key,V,KeyOfValue,Compare>::iterator& p);
public:
rb_tree_iterator() {} //noexcept //noexpect()表示()中如果为true则必然无异常,编译器不会再对其检查
explicit //explicit关键字表示不允许隐性构造
rb_tree_iterator(base_ptr x):M_node(x){}//noexcept
protected:
//对于end如果继续++那么还是end
void increment()//迭代器++,需要对end()特判
{
if(M_node->right!=nullptr)
//右孩子不为空,那么直接去左子树的最左偏
{
if(M_node==M_node->right)return;//
M_node=M_node->right;
M_node=rb_tree_node_base::get_min(M_node);
}
else
{
base_ptr M_parent=M_node->parent;
//如果当前节点一直是父节点的右孩子,
//那么需要一直找父亲的父亲,知道当前节点为父亲节点的左孩子,这个
//这个时候父亲节点即下一个
while(M_node==M_parent->right)
M_node=M_parent,M_parent=M_parent->parent;
//特判M_node为根节点的情况,即根节点只有左子树,没有右子树
//这个判断主要是为了end(),
//如果M已经是最右边的节点,那么理应返回end()即header
if(M_node->right!=M_parent)
M_node=M_parent;
}
}
//begin如果--那么会变成end
void decrement()//迭代器--,需要对begin()特判
{
TODO:嘶,红色说明不是根,那父亲的父亲怎么会是本身呢?
//答:特判header,如果是header,说明当前迭代器是end(),而header是红色的
//那么减去一个就变成了末迭代器。也就是header的右孩子,可以直接返回
if(M_node->parent==nullptr)return;
//所有节点都应该有父亲,但是当树为空且当前为header时不是这样的,对此特判
if(M_node->color==RED&&M_node->parent->parent==M_node)
M_node=M_node->right;
else if(M_node->left!=nullptr)//左孩子不为空
{
if(M_node==M_node->left)return;
M_node=M_node->left;
M_node=rb_tree_node_base::get_max(M_node);
}
else
{
base_ptr M_parent=M_node->parent;
while(M_node==M_parent->left)
M_node=M_parent,M_parent=M_parent->parent;
TODO:为什么--不需要对header特判?
//答:首先header表示end()而不是begin(),
//所以--之后即使变成end()也没有问题,不需要特判
M_node=M_parent;
}
}
public:
//解引用,返回值的引用
reference
operator*()const noexcept//const加在类中函数后面表示这个函数不会修改类中的
//值,如果修改会报错,除非值用Mutable修饰
{
//link_type需要转化成这样才能访问value
return Link_type(M_node)->value;
}
//返回value的指针,先解引用再取址,
TODO:为什么不直接返回this?
//答:pointer指的是value的指针,所以应该返回value的指针
pointer operator->()const noexcept
{
return &(operator*());
}
TODO:-----为什么operator++会有()和(int)两种?-----//
//返回迭代器的引用,这个是 ++it 会返回引用
//operator++()参数为空是这样的。
Self& operator++() noexcept
{
increment();
return *this;//这个地方返回的是迭代器本身
}
//返回迭代器的拷贝,这个是 it++ 不会返回引用,
//返回的是拷贝,operator++()参数为int是这样的
Self operator++(int)noexcept//it++后面不知道为什么会出现一个0
{
Self tmp=*this;
increment();
return tmp;//返回的是迭代器本身的拷贝
}
//和上面的同理。
Self& operator--()noexcept
{
decrement();
return *this;
}
Self operator--(int)noexcept
{
Self tmp=*this;
decrement();
return tmp;
}
//迭代器看的那个operator==有两个参数好像是老版本的。
bool operator==(const Self&other)const noexcept
{
return this->M_node==other.M_node;
}
bool operator!=(const Self&other)const noexcept
{
return this->M_node!=other.M_node;
}
//因为函数和传入的参数无关,所以没有命名
//我超,为什么新版没有这个反而。猜想可能是标准改成了可以直接使用
//struct里面typedef的
// std::bidirectional_iterator_tag iterator_category(const rb_tree_base_iterator&)
// {return std::bidirectional_iterator_tag();}
TODO:这个函数是干啥的?
//是返回指针类型的。
//template<typename Value,typename Ref,typename Ptr>
// inline Value* value_type(const rb_tree_iterator&)
// {
// return (Value*)0;
// //return nullptr;//返回空指针
// }
};
inline void
update_node_count(rb_tree_node_base*x)
{
if(x==nullptr)return;
x->node_count=1;
x->node_count+=(x->left==nullptr?0:x->left->node_count);
x->node_count+=(x->right==nullptr?0:x->right->node_count);
}
//------全局函数,左右旋--------//
//左旋,对x进行左旋,需要传入root作为参数
//左旋,必有右孩子
TODO:为什么这个传入root为引用型
//答:看下面
inline void //内联
rb_tree_rotate_left(rb_tree_node_base*x,rb_tree_node_base*&root)
{
rb_tree_node_base*y=x->right;
x->right=y->left;
if(y->left!=nullptr)
y->left->parent=x;
y->parent=x->parent;
//因为没有传入header,但是却需要,如果x是root的时候修改header的指针
//所以需要对root传入引用
if(x==root)
root=y;
//下面对父亲进行处理
else if(x==x->parent->left)
x->parent->left=y;
else
x->parent->right=y;
y->left=x;
x->parent=y;
update_node_count(x),update_node_count(y);
}
//右旋,必有左孩子
inline void
rb_tree_rotate_right(rb_tree_node_base*x,rb_tree_node_base*&root)
{
rb_tree_node_base*y=x->left;
x->left=y->right;
if(y->right!=nullptr)
y->right->parent=x;
y->parent=x->parent;
if(x==root)
root=y;
else if(x==x->parent->right)
x->parent->right=y;
else
x->parent->left=y;
y->right=x;
x->parent=y;
update_node_count(x),update_node_count(y);
}
//---------全局函数,红黑树的Rebalance,解决双红和双黑问题------//
//方法论:插入节点站在祖父,删除节点站在父亲
inline void
rb_tree_rebalance_for_insert(rb_tree_node_base*x,rb_tree_node_base*&root)
{
//x指向新插入的节点,新节点为红色
//同时x永远指向红色的节点。
x->color=RED;
rb_tree_node_base*parent=x->parent,*grandparent=parent->parent,*y,*p=x;
//站在祖父考虑问题。
while(x!=root&&parent->color==RED)
{
update_node_count(parent);
//左型
if(parent==grandparent->left)
{
y=grandparent->right;
//两个孩子都是红色,
//策略:本节点染红,两个孩子染黑,则满足性质
if(y!=nullptr&&y->color==RED)
{
parent->color=BLACK;
y->color=BLACK;
grandparent->color=RED;
x=grandparent;
//需要继续检查
update_node_count(x);
}
//左双红
//策略:分两种LL红和LR红,LR红需要先左旋
//然后,孩子染黑,父亲染红,
else
{
//LR型,先左旋
//这代码正确吗?
//if里面x=x->parent这个时候x的位置改变了啊,变成了父亲,抱歉,不该质疑
//左旋之前,x先移动到父亲,左旋之后x的位置又降下来了。
//所以每次旋转之后parent,grandparent都需要修改
if(x==parent->right)
{
x=parent;
rb_tree_rotate_left(x,root);
parent=x->parent;//需要刷新
grandparent=parent->parent;
}
parent->color=BLACK;//父亲染黑,祖父染红
grandparent->color=RED;
rb_tree_rotate_right(grandparent,root);//这个时候右旋,循环结束
//还得是stl,rebalance代码比我的简短多了。
}
}
else
{
y=grandparent->left;
if(y!=nullptr&&y->color==RED)
{
y->color=parent->color=BLACK;
grandparent->color=RED;
x=grandparent;
update_node_count(x);
}
else
{
if(x==parent->left)
{
x=parent;
rb_tree_rotate_right(x,root);
parent=x->parent;//需要刷新
grandparent=parent->parent;
}
parent->color=BLACK;
grandparent->color=RED;
rb_tree_rotate_left(grandparent,root);
}
}
parent=x->parent;
grandparent=parent->parent;
}
while(parent!=root)
update_node_count(parent),parent=parent->parent;
update_node_count(root);
root->color=BLACK;
}
//站在父亲节点
TODO:leftmost?rightmost?
inline rb_tree_node_base*
rb_tree_rebalance_for_erase(rb_tree_node_base*z,
rb_tree_node_base*&root,
rb_tree_node_base*&leftmost,
rb_tree_node_base*&rightmost)
{
TODO:x为什么始终指向空?x是干啥的啊?
rb_tree_node_base*y=z,*x=nullptr,*x_parent=nullptr;
//作用,让y指向被删除节点,x指向被删除节点的继任节点。
//x_parent指向删除y之后的x的父亲,之所以不直接 x->parent是因为x可能为空
if(y->left==nullptr)
x=y->right;
else if(y->right==nullptr)
x=y->left;
else
{
y=y->right;//需要直接后继;
y=rb_tree_node_base::get_min(y);
x=y->right;
}
//p=y;//指向后继。
TODO:老版本没有move函数,所以没有进行值替代,而是进行的指针替代
//这里为了方便进行值替代
//然而我想多了,如果想要值替代,需要传入的是rb_tree_node而不是rb_tree_node_base
//下面做的是把用y把z指针替代,同时用x把y指针替代。
if(y!=z)//y是z的后继,注意,这个时候z的左节点必然不是y但是右节点可能是,需要讨论
{
z->left->parent=y;
y->left=z->left;
if(y!=z->right) //对y不是z的右节点特判
{
x_parent=y->parent;//x_parent
if(x!=nullptr)x->parent=y->parent;
y->parent->left=x;//y一定在父亲的左边,因为是后继
y->right=z->right;
z->right->parent=y;
}
else
x_parent=y;
//把z摘下来,y放上去。
if(root==z)
root=y;
else if(z->parent->left==z)
z->parent->left=y;
else
z->parent->right=y;
y->parent=z->parent;
std::swap(y->color,z->color);
//update_node_count(y);
y=z;
// __y now points to node to be actually deleted
}
else//z本身就只剩一个孩子,所以y==z
{
x_parent=y->parent;
if(x!=nullptr)x->parent=y->parent;
//update_node_count(y);
if(root==z)
root=x;
else if(z->parent->left==z)
z->parent->left=x;
else
z->parent->right=x;
if(leftmost==z)
{
if(z->right==nullptr)
leftmost=z->parent;
else
leftmost=rb_tree_node_base::get_min(x);
}
if(rightmost==z)
{
if(z->left==nullptr)
rightmost=z->parent;
else
rightmost=rb_tree_node_base::get_max(x);
}
}
if(y->color==BLACK)//如果删除的是黑色节点,这个时候处理双黑问题
{
rb_tree_node_base*brother;//指向x的兄弟
while(x!=root&&(x==nullptr||x->color==BLACK))
{
update_node_count(x_parent);
if(x==x_parent->left)
{
brother=x_parent->right;
//右兄弟有红,这个时候有以下条件:
//1.父亲为黑 2.右兄弟必有两个黑色孩子
//3.右兄弟的两个黑色孩子可能还有红色孩子
//策略:兄弟染黑,父亲染红,父亲左旋
//这个时候x,x_parent相对位置没有变,
//但是x_parent变成了红色,问题转化
if(brother->color==RED)
{
brother->color=BLACK;
x_parent->color=RED;
rb_tree_rotate_left(x_parent,root);
brother=x_parent->right;
}
//兄弟为黑,且孩子双黑,这个时候需要进一步调整,进入下一次循环。
//因为删去的节点为黑色,可以知道,左子树比右子树少了一个黑色路径。
if((brother->left==nullptr||brother->left->color==BLACK)&&
(brother->right==nullptr||brother->right->color==BLACK))
{
//如果父亲为红色,那么这里可能会出现双红现象。在while循环最下面进行了处理。
//还以为没有考虑父亲为红色呢,不该质疑
brother->color=RED;
x=x_parent;
x_parent=x_parent->parent;
}
else//兄弟为黑,且至少有一个红孩子
{
if(brother->right==nullptr||brother->right->color==BLACK)
{
TODO:这个判断是必要的吗?
//左节点应该必然存在并且是红色的啊
if(brother->left!=nullptr)
brother->left->color=BLACK;
//RL型红色,先右旋
brother->color=RED;
rb_tree_rotate_right(brother,root);
brother=x_parent->right;
}
brother->color=x_parent->color;
x_parent->color=BLACK;
//这里也不应该啊,这里应该必然为红色啊。
if(brother->right!=nullptr)
brother->right->color=BLACK;
rb_tree_rotate_left(x_parent,root);
break;
}
}
else
{
brother=x_parent->left;
if(brother->color==RED)
{
brother->color=BLACK;
x_parent->color=RED;
rb_tree_rotate_right(x_parent,root);
brother=x_parent->left;
}
if((brother->right==nullptr||brother->right->color==BLACK)&&
(brother->left==nullptr||brother->left->color==BLACK))
{
brother->color=RED;
x=x_parent;
x_parent=x_parent->parent;
}
else
{
if(brother->left==nullptr||brother->left->color==BLACK)
{
if(brother->right!=nullptr)
brother->right->color=BLACK;
brother->color=RED;
rb_tree_rotate_left(brother,root);
brother=x_parent->left;
}
brother->color=x_parent->color;
x_parent->color=BLACK;
if(brother->left!=nullptr)
brother->left->color=BLACK;
rb_tree_rotate_right(x_parent,root);
break;
}
}
}
if(x!=nullptr)x->color=BLACK;
}
while(x_parent!=root)
update_node_count(x_parent),x_parent=x_parent->parent;
update_node_count(root);
return y;//返回y,y是待删除节点,这个应该是来删除的(为什么不直接在这里删除?)
}
//正活开始。
template<typename Value>
struct rb_tree_base
{
rb_tree_base():M_header(nullptr){M_header=new rb_tree_node<Value>;}
~rb_tree_base(){M_put_node(M_header);}
protected:
rb_tree_node<Value>* M_header;
rb_tree_node<Value>* M_get_node(const Value &v)
{
rb_tree_node<Value>*tmp=new rb_tree_node<Value>(v);
tmp->left=tmp->right=tmp->parent=nullptr;
tmp->color=RED;
return tmp;
}
void M_put_node(rb_tree_node<Value>*p)
{
delete p;
}
};
//KeyOfValue是仿函数,用于取出需要比较的值
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
class Rb_tree:protected rb_tree_base<Value> //继承于rb_tree_base,天生有一个初始化好的头结点。
{
typedef rb_tree_base<Value> Base;
typedef Rb_tree<Key,Value,KeyOfValue,Compare> RB_Self;
protected:
typedef rb_tree_node_base* Base_ptr;
typedef rb_tree_node<Value> Rb_tree_node;
public:
typedef Key key_type;
typedef Value value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef Rb_tree_node* Link_type;
typedef unsigned long long size_type;
typedef std::ptrdiff_t difference_type;
protected:
//rb_tree_node<Value>* M_header;
Link_type M_create_node(const value_type& x)
{
Link_type tmp=this->M_get_node(x);
return tmp;
}
Link_type M_clone_node(Link_type x)
{
Link_type tmp=new Rb_tree_node(x->value);
tmp->color=x->color;
tmp->left=tmp->right=nullptr;
return tmp;
}
void destory_node(Link_type p)
{
//Destproy就是调用析构函数,对于new出来的则delete
std::_Destroy(&p->value);
this->M_put_node(p);
}
protected:
size_type M_node_count;
Compare M_key_compare;
Link_type& M_root()const{
return (Link_type&) this->M_header->parent;
}
Link_type& M_leftmost()const{
return (Link_type&) this->M_header->left;
}
Link_type& M_rightmost()const{
return (Link_type&) this->M_header->right;
}
static Link_type& S_left(Link_type x){
return (Link_type&)(x->left);
}
static Link_type& S_right(Link_type x){
return (Link_type&)(x->right);
}
static Link_type& S_parent(Link_type x){
return (Link_type&)(x->parent);
}
static reference S_value(Link_type x){
return x->value;
}
static const Key& S_key(Link_type x){
return KeyOfValue()(S_value(x));
}
// static bool& S_color(Link_type x){
// return (bool&)(x->color);
// }
static Link_type& S_left(Base_ptr __x)
{ return (Link_type&)(__x->left); }
static Link_type& S_right(Base_ptr __x)
{ return (Link_type&)(__x->right); }
static Link_type& S_parent(Base_ptr __x)
{ return (Link_type&)(__x->parent); }
static reference S_value(Base_ptr __x)
{ return ((Link_type)__x)->value; }
static const Key& S_key(Base_ptr __x)
{ return KeyOfValue()(S_value(Link_type(__x)));}
static bool& S_color(Base_ptr __x)
{ return (bool&)(Link_type(__x)->color); }
static Link_type S_minimum(Link_type __x)
{ return (Link_type) rb_tree_node_base::get_min(__x); }
static Link_type S_maximum(Link_type __x)
{ return (Link_type) rb_tree_node_base::get_max(__x); }
public:
typedef rb_tree_iterator<value_type> iterator;
private:
iterator M_insert(Base_ptr x,Base_ptr y,const value_type& v);
Link_type M_copy(Link_type x,Link_type p);
void M_erase(Link_type x);
Base_ptr& get_M_node(iterator& p)
{return p.M_node;}
public:
Rb_tree():
M_node_count(0),M_key_compare()
{M_empty_initilaize();}
Rb_tree(const Compare&comp):
M_node_count(0),M_key_compare(comp)
{M_empty_initilaize();}
//也是深拷贝
TODO:
Rb_tree(const RB_Self&x):
M_node_count(0),M_key_compare(x.M_key_compare)
{
if(x.M_root()==nullptr)
M_empty_initilaize();
else
{
S_color(this->M_header)=RED;
M_root()=M_copy(x.M_root(),this->M_header);
M_leftmost()=S_minimum(M_root());
M_rightmost()=S_maximum(M_root());
}
M_node_count=x.M_node_count;
}
~Rb_tree(){clear();}
//深拷贝
RB_Self& operator=(const RB_Self&x);
private:
void M_empty_initilaize()
{
//M_header->color=RED;
S_color(this->M_header)=RED;
M_root()=nullptr;
M_leftmost()=this->M_header;
M_rightmost()=this->M_header;
}
public:
Compare key_comp() const {return M_key_compare;}
iterator begin() {return iterator(M_leftmost());}
iterator end() {return iterator(this->M_header);}
bool empty()const {return M_node_count==0;}
size_type size()const {return M_node_count;}
size_type max_size() const{return size_type(-1);}
//只需要换header,count和compare
void swap(RB_Self&t)
{
std::swap(this->M_header,t.M_header);
std::swap(M_node_count,t.M_node_count);
std::swap(M_key_compare,t.M_key_compare);
}
public:
std::pair<iterator,bool> insert_unique(const value_type&x);
iterator insert_equal(const value_type&x);
//将x插入rb,保持节点独一无二
iterator insert_unique(iterator position,const value_type&x);
//允许节点重复
iterator insert_equal(iterator position,const value_type&x);
//这里和新保持一致,erase之后应该返回下一个迭代器
iterator erase(iterator position);
size_type erase(const key_type&x);
iterator erase(iterator first,iterator last);
void clear()
{
if(M_node_count>0)
{
M_erase(M_root());
M_leftmost()=this->M_header;
M_rightmost()=this->M_header;
M_root()=nullptr;
M_node_count=0;
}
}
public:
iterator find(const key_type&x);
size_type count(const key_type&x)const;
iterator lower_bound(const key_type&x);
iterator upper_bound(const key_type&x);
//由值获得排名
size_type get_rank(const key_type&x);
//由排名获得值(迭代器)
iterator get_val(size_t x);
std::pair<iterator,iterator> equal_range(const key_type&x);
bool __rb_verify();//debugging
//这个放在里面,后面一个放在里面,
bool operator==(const RB_Self&x)const
{
return size()==x.size()&&
std::equal(begin(),end(),x.begin());
}
};
//类外定义函数::::方法
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::RB_Self&
Rb_tree<Key,Value,KeyOfValue,Compare>
::operator=(const RB_Self&x)
{
if(this!=&x)
{
clear();
M_node_count=0;
M_key_compare=x.M_key_compare;
if(x.M_root()==nullptr)
{
M_root()=nullptr;
M_leftmost()=this->M_header;
M_rightmost()=this->M_header;
}
else
{
M_root()=M_copy(x.M_root(),this->M_header);
M_leftmost()=S_minimum(M_root());
M_rightmost()=S_maximum(M_root());
M_node_count=x.M_node_count;
}
}
return *this;
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
M_insert(Base_ptr a,Base_ptr b,const value_type & v)
{
//x是新值插入点,y是x的父节点,v是插入值,z是新节点。
Link_type x=(Link_type)a,y=(Link_type)b,z=nullptr;
if(y==this->M_header||x!=nullptr||
M_key_compare(KeyOfValue()(v),S_key(y)))
{
z=M_create_node(v);
S_left(y)=z;
if(y==this->M_header)
{
M_root()=z;
M_rightmost()=z;
}
else if(y==M_leftmost())
{
M_leftmost()=z;
}
}
else
{
z=M_create_node(v);
S_right(y)=z;
if(y==M_rightmost())
M_rightmost()=z;
}
S_parent(z)=y;
S_left(z)=S_right(z)=nullptr;
rb_tree_rebalance_for_insert(z,this->M_header->parent);
++M_node_count;
return iterator(z);
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
void
Rb_tree<Key,Value,KeyOfValue,Compare>::
M_erase(Link_type x)
//删除子树,这是没有平衡的直接删除,应当只在clear函数中调用。
{
//后序遍历,
while(x!=nullptr)
{
M_erase(S_right(x));
Link_type y=S_left(x);
destory_node(x);
x=y;
}
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
insert_equal(const Value&v)
//我怎么记得新版本这里是直接用的lower_bound
{
Link_type y=this->M_header,x=M_root();
while(x!=nullptr)
{
y=x;
x=M_key_compare(KeyOfValue()(v),S_key(x))?
S_left(x):S_right(x);
}
return M_insert(x,y,v);
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
std::pair<typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator,bool>
Rb_tree<Key,Value,KeyOfValue,Compare>::
insert_unique(const Value&v)
{
Link_type y=this->M_header,x=M_root();
bool comp=true;
while(x!=nullptr)
{
y=x;
comp=M_key_compare(KeyOfValue()(v),S_key(x));
x=comp?S_left(x):S_right(x);
}
iterator j=iterator(y);//j为插入节点的父节点
//true表示插入父亲节点的左边。
if(comp)
{
//如果j是begin,那么应该直接插入,不能在减--j
if(j==begin())
return std::pair<iterator,bool>(M_insert(x,y,v),true);
else
--j;
}
//分析一下:
//1.M_key_compare重载的应该是小于号
//2.x指向要么等于j,要么在j的右节点。
//3.这个if语句继续进行比较的是j和和x
//综上
//1.如果if通过,要么x和j指向相同同时j小于x,要么x在j的右节点同时j小于x
//2.显然前者排除,所以得出结论,如果执行if,必然是x在j的右节点,同时两者值不同。
if(M_key_compare(KeyOfValue()(*j),KeyOfValue()(v)))
return std::pair<iterator,bool>(M_insert(x,y,v),true);
//上面两个if都没有通过,说明存在相同的节点,返回j(相同的节点),false
return std::pair<iterator,bool>(j,false);
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
insert_unique(iterator position,const Value&v)
{
if(get_M_node(position)==this->M_header->left)//begin()
{
if(size()>0&&
M_key_compare(KeyOfValue()(v),S_key(get_M_node(position))))
{
return M_insert(get_M_node(position),get_M_node(position),v);
}
else
return insert_unique(v).first;
}
else if(get_M_node(position)==this->M_header)
{
if(M_key_compare(S_key(M_rightmost()),KeyOfValue()(v)))
{
return M_insert(nullptr,M_rightmost(),v);
}
else
return insert_unique(v).first;
}
else
{
iterator before=position;
--before;
//在before和position之间
if(M_key_compare(S_key(get_M_node(before)),KeyOfValue()(v))&&
M_key_compare(KeyOfValue()(v),S_key(get_M_node(position))))
{
if(S_right(get_M_node(before))==nullptr)
return M_insert(nullptr,get_M_node(before),v);
else
return M_insert(get_M_node(position),get_M_node(position),v);
}
else
return insert_unique(v).first;
}
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
insert_equal(iterator position,const Value&v)
{
if(get_M_node(position)==this->M_header->left)
{
if(size()>0&&//position不大于v
!M_key_compare(S_key(get_M_node(position)),KeyOfValue()(v)))
return M_insert(get_M_node(position),get_M_node(position),v);
else
return insert_equal(v);
}
else if(get_M_node(position)==this->M_header)
{
if(!M_key_compare(KeyOfValue()(v),S_key(M_rightmost())))
return M_insert(nullptr,M_rightmost(),v);
else
return insert_equal(v);
}
else
{
iterator before=position;
--before;
if(!M_key_compare(KeyOfValue()(v),S_key(get_M_node(before)))&&
!M_key_compare(S_key(get_M_node(position)),KeyOfValue()(v)))
if(S_right(get_M_node(before))==nullptr)
return M_insert(nullptr,get_M_node(before),v);
else
return M_insert(get_M_node(before),get_M_node(before),v);
else
return insert_equal(v);
}
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
erase(iterator position)
{
if(position==end())return end();
iterator successor=position;
++successor;
rb_tree_node_base* y=rb_tree_rebalance_for_erase(
get_M_node(position),
this->M_header->parent,
this->M_header->left,
this->M_header->right
);
destory_node((Link_type)y);
--M_node_count;
return successor;
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::size_type
Rb_tree<Key,Value,KeyOfValue,Compare>::
erase(const Key&x)
{
std::pair<iterator,iterator> p=equal_range(x);
size_type n=std::distance(p.first,p.second);
erase(p.first,p.second);
return n;
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::Link_type
Rb_tree<Key,Value,KeyOfValue,Compare>::
M_copy(Link_type x,Link_type p)//拷贝一个子树。使用递归算法。
{
Link_type top=M_clone_node(x);
top->parent=p;
try
{
if(x->right!=nullptr)
top->right=M_copy(S_right(x),top);//递归
p=top;
x=S_left(x);
while(x!=nullptr)
{
Link_type y=M_clone_node(x);
p->left=y;
y->parent=p;
if(x->right!=nullptr)
y->right=M_copy(S_right(x),y);
p=y;
x=S_left(x);
}
}
catch(...)
{
M_erase(top);
throw;
}
return top;
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
erase(iterator first,iterator last)
{
if(first==begin()&&last==end())
{
clear();
return end();
}
else
{
while(first!=last)
erase(first++);
return last;
}
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
find(const key_type&k)
{
Link_type y=this->M_header,x=M_root();//y是last node while is not less than k
//y指向x的下一个迭代器
while(x!=nullptr)
//如果x>=k就向左,同时为了保持y是x下一个迭代器,y刷新
//为什么不M_key_compare(k,x)?因为那样的话是 > 而我们需要的是 >=
if(!M_key_compare(S_key(x),k))
y=x,x=S_left(x);
else
x=S_right(x);
iterator j=iterator(y);
//j如果是end,显然直接返回end,
//所求j应该>=k,如果k<j取真,说明 j>k 不存在k这个节点,
return (j==end()||M_key_compare(k,KeyOfValue()(*j)))?
end():j;
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::size_type
Rb_tree<Key,Value,KeyOfValue,Compare>::
count(const Key&k)const
{
std::pair<iterator,iterator> p=equal_range(k);
size_type n=0;
std::distance(p.first,p.second,n);
return n;
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
lower_bound(const Key&k)
{
Link_type y=this->M_header,x=M_root();
//这部分和find一致
while(x!=nullptr)
if(!M_key_compare(S_key(x),k))
y=x,x=S_left(x);
else
x=S_right(x);
return iterator(y);
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
upper_bound(const Key&k)
{
Link_type y=this->M_header,x=M_root();
//改成了M_key_compare(k,S_key(x))而已
while(x!=nullptr)
if(M_key_compare(k,S_key(x)))
y=x,x=S_left(x);
else
x=S_right(x);
return iterator(y);
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator
Rb_tree<Key,Value,KeyOfValue,Compare>::
get_val(size_t x)
{
Link_type y=M_root();
while (y!=nullptr)
{
if( (y->left==nullptr?0:y->left->node_count)+1 == x)
break;
else if( (y->left==nullptr?0:y->left->node_count) >= x)
y=S_left(y);
else
{
x-= (y->left==nullptr?0:y->left->node_count) +1;
y=S_right(y);
}
}
return iterator(y);
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
typename Rb_tree<Key,Value,KeyOfValue,Compare>::size_type
Rb_tree<Key,Value,KeyOfValue,Compare>::
get_rank(const key_type&x)
{
Link_type y=M_root();
size_type rank=1;
while(y!=nullptr)
{
if(!M_key_compare(S_key(y),x))//x<=S_key(y)
y=S_left(y);
else
{
rank+=(y->left==nullptr?0:y->left->node_count)+1;
y=S_right(y);
}
}
return rank;
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
std::pair<typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator,typename Rb_tree<Key,Value,KeyOfValue,Compare>::iterator>
Rb_tree<Key,Value,KeyOfValue,Compare>::
equal_range(const Key&k)
{
return std::pair<iterator,iterator>(lower_bound(k),upper_bound(k));
}
inline int black_count(rb_tree_node_base*node,rb_tree_node_base*root)
{
if(node==0)
return 0;
else
{
int bc=node->color==BLACK?1:0;
if(node==root)
return bc;
else
return bc+black_count(node->parent,root);
}
}
template<typename Key,typename Value,typename KeyOfValue,typename Compare>
bool
Rb_tree<Key,Value,KeyOfValue,Compare>::
__rb_verify()
{
if(M_node_count==0||begin()==end())
return M_node_count==0&&begin()==end()&&
this->M_header->left==this->M_header&&this->M_header->right==this->M_header;
int len=black_count(M_leftmost(),M_root());
for(iterator it=begin();it!=end();++it)
{
Link_type x=(Link_type)get_M_node(it);
Link_type L=S_left(x);
Link_type R=S_right(x);
if(x->color==RED&&((L!=nullptr&&L->color==RED)||
(R!=nullptr&&R->color==RED)))
return false;
if(L!=nullptr&&M_key_compare(S_key(x),S_key(L)))
return false;
if(R!=nullptr&&M_key_compare(S_key(R),S_key(x)))
return false;
if(L==nullptr&&R==nullptr&&black_count(x,M_root())!=len)
return false;
}
if(M_leftmost()!=rb_tree_node_base::get_min(M_root()))
return false;
if(M_rightmost()!=rb_tree_node_base::get_max(M_root()))
return false;
return true;
}
template<typename Key,typename Value,typename KeyofValue,typename Compare>
struct rb_tree:public Rb_tree<Key,Value,KeyofValue,Compare>
{
typedef Rb_tree<Key,Value,KeyofValue,Compare> Base;
rb_tree(const Compare&comp=Compare()) :Base(comp){}
~rb_tree(){}
};
}
//因为有 my_map 会包含所以这里没有包含 my_rb_tree.h,只做调试使用
namespace my_multimap {
template<typename Key,typename Tp,
typename Compare=std::less<Key>>
class multimap{
public:
typedef Key key_type;
typedef Tp data_type;
typedef Tp mapped_type;
typedef std::pair<const Key,Tp> value_type;
typedef Compare key_compare;
private:
struct value_compare
{
friend class multimap<Key,Tp,Compare>;
public:
const key_type& operator()(const value_type&x)const{
return x.first;
}
};
private:
//red-black tree representing map
typedef my_rb_tree::Rb_tree<key_type,value_type,
value_compare,key_compare> Rep_type;
Rep_type M_t;
public:
typedef typename Rep_type::pointer pointer;
typedef typename Rep_type::reference reference;
typedef typename Rep_type::iterator iterator;
typedef typename Rep_type::size_type size_type;
typedef typename Rep_type::difference_type difference_type;
multimap():M_t(Compare()){}
explicit multimap(const Compare&comp):
M_t(comp){}
multimap(const multimap<Key,Tp,Compare>&x):M_t(x.M_t){}
multimap<Key,Tp,Compare>&
operator=(const multimap<Key,Tp,Compare>&x)
{
M_t=x.M_t;
return *this;
}
private:
key_compare key_comp() const {return M_t.key_comp();}
value_compare value_compare() const {return value_compare(M_t.key_comp());}
public:
bool verify(){return M_t.__rb_verify();}
iterator begin() {return M_t.begin();}
iterator end() {return M_t.end();}
bool empty() const {return M_t.empty();}
size_type size() const {return M_t.size();}
size_type max_size() const {return M_t.max_size();}
void swap(multimap<Key,Tp,Compare>&x){M_t.swap(x.M_t);}
std::pair<iterator,bool> insert_unique(const value_type&x)
{return M_t.insert_unique(x);}
iterator insert_unique(iterator position,const value_type&x)
{
return M_t.insert_unique(position,x);
}
iterator insert_equal(const value_type&x)
{return M_t.insert_equal(x);}
iterator insert_equal(iterator position,const value_type&x)
{return M_t.insert_equal(position,x);}
iterator erase(iterator position){return M_t.erase(position);}
size_type erase(const key_type&x){return M_t.erase(x);}
iterator erase(iterator first,iterator second)
{return M_t.erase(first,second);}
void clear(){M_t.clear();}
iterator find(const key_type&x){return M_t.find(x);}
size_type count(const key_type&x){
if(find(x)==end())return 0;
iterator upper=upper_bound(x);
//没有和stl一样使用distance的原因:不能保证效率,这么做可以稳定获得logn的时间复杂度。
return (upper==end()?size()+1:get_rank(upper->first) )-get_rank(x);
}
iterator lower_bound(const key_type&x){return M_t.lower_bound(x);}
iterator upper_bound(const key_type&x){return M_t.upper_bound(x);}
iterator get_val(size_t x){return M_t.get_val(x);}
size_t get_rank(const key_type&x){return M_t.get_rank(x);}
std::pair<iterator,iterator> equal_range(const key_type&x){
return M_t.equal_range(x);
}
bool operator==(const multimap<Key,Tp,Compare>&x)const{
return x.M_t==M_t;
}
bool operator!=(const multimap<Key,Tp,Compare>&x)const{
return !(x.M_t==M_t);
}
};
}
int main()
{
std::ios::sync_with_stdio(false);
std::cout.tie(0),std::cin.tie(0);
my_multimap::multimap<int,int> mp;
int t,op,x;
std::cin>>t;
while (t--)
{
std::cin>>op>>x;
//std::cout<<t<<' '<<mp.verify()<<std::endl;
if(op==1)
{
mp.insert_equal({x,x});
}
else if(op==2)
{
mp.erase(mp.find(x));
}
else if(op==3)
{
std::cout<<mp.get_rank(x)<<'\n';
}
else if(op==4)
{
std::cout<< mp.get_val(x)->first <<'\n';
}
else if(op==5)
{
auto it=mp.lower_bound(x);
if(it==mp.end()||it->first>=x)
--it;
std::cout<< it->first<<'\n';
}
else if(op==6)
{
auto it=mp.upper_bound(x);
std::cout<< it->first<<'\n';
}
}
std::cout<<std::endl;
system("pause");
return 0;
}