深入理解STL之RBTree重点讲义资料Word文档下载推荐.docx
- 文档编号:18449167
- 上传时间:2022-12-16
- 格式:DOCX
- 页数:30
- 大小:599.30KB
深入理解STL之RBTree重点讲义资料Word文档下载推荐.docx
《深入理解STL之RBTree重点讲义资料Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《深入理解STL之RBTree重点讲义资料Word文档下载推荐.docx(30页珍藏版)》请在冰豆网上搜索。
因本人能力有限可能无法将红黑树讲得很清楚全面,而且STL红黑树的实现也较为复杂,建议先到下面推荐的几篇博客里去补补知识
∙教你初步了解红黑树
∙【数据结构和算法05】红-黑树(看完包懂~)
∙一步一图一代码,一定要让你真正彻底明白红黑树
红黑树的节点结构
红黑树的节点在二叉树的节点结构上增加了颜色属性,而且,为了更好的进行插入和删除操作,进而增加了指向父节点的指针。
为了更好的弹性,STL红黑树的节点采用双层设计,将不依赖模板的参数提取出来,作为base结构,然后用带模板的节点结构取继承它。
下面是红黑树节点结构的源码:
typedefbool__rb_tree_color_type;
const__rb_tree_color_type__rb_tree_red=false;
//紅色為0
const__rb_tree_color_type__rb_tree_black=true;
//黑色為1
struct__rb_tree_node_base
{
typedef__rb_tree_color_typecolor_type;
typedef__rb_tree_node_base*base_ptr;
color_typecolor;
//节点颜色
base_ptrparent;
//指向父节点
base_ptrleft;
//指向左子节点
base_ptrright;
//指向右子节点
//一直往左走,就能找到红黑树的最小值节点
//二叉搜索树的性质
staticbase_ptrminimum(base_ptrx)
{
while(x->
left!
=0)x=x->
left;
returnx;
}
//一直往右走,就能找到红黑树的最大值节点
staticbase_ptrmaximum(base_ptrx)
right!
right;
};
//真正的节点定义,采用双层节点结构
//基类中不包含模板参数
template<
classValue>
struct__rb_tree_node:
public__rb_tree_node_base
typedef__rb_tree_node<
Value>
*link_type;
Valuevalue_field;
//節點實值
红黑树的迭代器
为了将RBtree实现为一个泛型容器,迭代器的设计很关键。
我们要考虑它的型别,以及前进(increment)、后退(devrement)、提领(dereference)和成员访问(memberaccess)等操作。
迭代器和节点一样,采用双层设计,STL红黑树的节点__rb_tree_node继承于__rb_tree_node_base;
STL的迭代器结构__rb_tree_iterator继承于__rb_tree_base_iterator,我们可以用一张图来解释这样的设计目的。
将这些分开设计,可以保证对节点和迭代器的操作更具有弹性。
下面来看迭代器的源码:
struct__rb_tree_base_iterator
typedef__rb_tree_node_base:
:
base_ptrbase_ptr;
typedefbidirectional_iterator_tagiterator_category;
typedefptrdiff_tdifference_type;
base_ptrnode;
//用来连接红黑树的节点
//寻找该节点的后继节点上
voidincrement()
if(node->
=0){//如果存在右子节点
node=node->
//直接跳到右子节点上
while(node->
=0)//然后一直往左子树走,直到左子树为空
else{//没有右子节点
base_ptry=node->
parent;
//找出父节点
while(node==y->
right){//如果该节点一直为它的父节点的右子节点
node=y;
//就一直往上找,直到不为右子节点为止
y=y->
=y)//若此时该节点不为它的父节点的右子节点
//此时的父节点即为要找的后继节点
//否则此时的node即为要找的后继节点,此为特殊情况,如下
//我们要寻找根节点的下一个节点,而根节点没有右子节点
//此种情况需要配合rbtree的header节点的特殊设计,后面会讲到
}
//寻找该节点你的前置节点
voiddecrement()
color==__rb_tree_red&
&
//如果此节点是红节点
node->
parent->
parent==node)//且父节点的父节点等于自己
//则其右子节点即为其前置节点
//以上情况发生在node为header时,即node为end()时
//注意:
header的右子节点为mostright,指向整棵树的max节点,后面会有解释
elseif(node->
=0){//如果存在左子节点
//跳到左子节点上
while(y->
=0)//然后一直往右找,知道右子树为空
//则找到前置节点
else{//如果该节点不存在左子节点
//跳到它的父节点上
left){//如果它等于它的父子节点的左子节点
//则一直往上查找
}//直到它不为父节点的左子节点未知
//此时他的父节点即为要找的前置节点
}
classValue,classRef,classPtr>
struct__rb_tree_iterator:
public__rb_tree_base_iterator
//配合迭代器萃取机制的一些声明
typedefValuevalue_type;
typedefRefreference;
typedefPtrpointer;
typedef__rb_tree_iterator<
Value,Value&
Value*>
iterator;
Value,constValue&
constValue*>
const_iterator;
Value,Ref,Ptr>
self;
//迭代器的构造函数
__rb_tree_iterator(){}
__rb_tree_iterator(link_typex){node=x;
__rb_tree_iterator(constiterator&
it){node=it.node;
//提领和成员访问函数,重载了*和->
操作符
referenceoperator*()const{returnlink_type(node)->
value_field;
pointeroperator->
()const{return&
(operator*());
//前置++和后置++
self&
operator++(){increment();
return*this;
selfoperator++(int){
selftmp=*this;
increment();
//直接调用increment函数
returntmp;
//前置--和后置--
operator--(){decrement();
selfoperator--(int){
decrement();
//直接调用decrement函数
在上述源代码中,一直提到STLRBTree特殊节点header的设计,这个会在RBTree结构中讲到,下面跟着我一起继续往下看吧。
红黑树的数据结构
有了上面的节点和迭代器设计,就能很好的定义出一颗RBTree了。
废话不多说,一步一步来剖析源代码吧。
classKey,classValue,classKeyOfValue,classCompare,
classAlloc=alloc>
classrb_tree{
protected:
typedefvoid*void_pointer;
rb_tree_node;
typedefsimple_alloc<
rb_tree_node,Alloc>
rb_tree_node_allocator;
//专属配置器
public:
//一些类型声明
typedefKeykey_type;
typedefvalue_type*pointer;
typedefconstvalue_type*const_pointer;
typedefvalue_type&
reference;
typedefconstvalue_type&
const_reference;
typedefrb_tree_node*link_type;
typedefsize_tsize_type;
//RB-tree的数据结构
size_typenode_count;
//记录树的节点个数
link_typeheader;
//header节点设计
Comparekey_compare;
//节点间的键值大小比较准则
//以下三个函数用来取得header的成员
link_type&
root()const{return(link_type&
)header->
leftmost()const{return(link_type&
rightmost()const{return(link_type&
//以下六个函数用来取得节点的成员
staticlink_type&
left(link_typex){return(link_type&
)(x->
left);
right(link_typex){return(link_type&
right);
parent(link_typex){return(link_type&
parent);
staticreferencevalue(link_typex){returnx->
staticconstKey&
key(link_typex){returnKeyOfValue()(value(x));
staticcolor_type&
color(link_typex){return(color_type&
color);
//以下六个函数用来取得节点的成员,由于双层设计,导致这里需要两个定义
left(base_ptrx){return(link_type&
right(base_ptrx){return(link_type&
parent(base_ptrx){return(link_type&
staticreferencevalue(base_ptrx){return((link_type)x)->
key(base_ptrx){returnKeyOfValue()(value(link_type(x)));
}
color(base_ptrx){return(color_type&
)(link_type(x)->
//求取极大值和极小值,这里直接调用节点结构的函数极可
staticlink_typeminimum(link_typex){
return(link_type)__rb_tree_node_base:
minimum(x);
staticlink_typemaximum(link_typex){
maximum(x);
//RBTree的迭代器定义
value_type,reference,pointer>
value_type,const_reference,const_pointer>
Comparekey_comp()const{returnkey_compare;
}//由于红黑树自带排序功能,所以必须传入一个比较器函数
iteratorbegin(){returnleftmost();
}//RBTree的起始节点为左边最小值节点
const_iteratorbegin()const{returnleftmost();
iteratorend(){returnheader;
}//RBTree的终止节点为右边最大值节点
const_iteratorend()const{returnheader;
boolempty()const{returnnode_count==0;
}//判断红黑树是否为空
size_typesize()const{returnnode_count;
}//获取红黑树的节点个数
size_typemax_size()const{returnsize_type(-1);
}//获取红黑树的最大节点个数,
//没有容量的概念,故为sizetype最大值
我们看到,在RBTree的数据结构中,定义了RBTree节点和迭代器,然后添加了header节点,以及node_count参数,其他都是一下简单的函数声明和类型声明。
除此之外,并没有过多的增加东西。
这里理解起来还是比较简单,至于header有什么作用,请继续往下看。
红黑树的构造与内存管理
红黑树的构造函数
红黑树的空构造函数将创建一个空树,此”空树“非彼二叉树的空树也。
空构造函数首先配置一个节点空间,使header指向该节点空间,然后将header的leftmost和rightmost指向自己,父节点指向0。
非空的STLRBTree中,header和root之间互为父节点,然后header的leftmost始终指向该树的最小值节点,rightmost始终指向该树的最大值节点,其示例图如下(左图为空树,右图为非空树):
下面来看看它的构造函数代码吧:
//这部分代码是从红黑树的结构定义中提取出来的
link_typeget_node(){returnrb_tree_node_allocator:
allocate();
}//配置空间
link_typecreate_node(constvalue_type&
x){
link_typetmp=get_node();
//配置空間
__STL_TRY{
construct(&
tmp->
value_field,x);
//构造内容
__STL_UNWIND(put_node(tmp));
//初始化函数,用来初始化一棵RBTree
voidinit(){
header=get_node();
//产生一个节点空间,令header指向它
color(header)=__rb_tree_red;
//令header为红色,用来区分header和root
root()=0;
leftmost()=header;
//令header的左子节点为其自己
rightmost()=header;
//令header的右子节点为其自己
//真正的默认构造函数
rb_tree(constCompare&
comp=Compare())
:
node_count(0),key_compare(comp){init();
}//直接调用初始化函数
//带参构造函数,以另一棵RBTree为初值来初始化
rb_tree(constrb_tree<
Key,Value,KeyOfValue,Compare,Alloc>
x)
node_count(0),key_compare(x.key_compare)
{
//產生一個節點空間,令header指向它
//令header為紅色
if(x.root()==0){//如果x是個空白樹
//令header的左子節點為自己。
//令header的右子節點為自己。
else{//x不是一個空白樹
root()=__copy(x.root(),header);
//调用copy函数
__STL_UNWIND(put_node(header));
leftmost()=minimum(root());
//令header的左子節點為最小節點
rightmost()=maximum(root());
//令header的右子節點為最大節點
node_count=x.node_count;
//copy函数定义
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 深入 理解 STL RBTree 重点 讲义 资料