关联式容器
实现:红黑树,按照键值大小将元素放于适当位置
内部结构:平衡二叉树
含义:每个元素都有键值与实值
二叉搜索树:对数时间的元素插入和访问,节点键值大于左子树中每个节点键值,小于右子树中每个节点键值
平衡二叉树:任意节点的左右子树的高度之差的绝对值<=1
4种不平衡状况:
1)左子节点左子树插入:左旋即可
2)右子节点右子树插入: 右旋即可
3)左子节点右子树插入: 先左后右旋转即可
4)右子节点左子树插入:先右后左旋转即可
1),2)属于外侧插入,3),4)属于内侧插入
红黑树:
条件:
1每个节点不是红色就是黑色
2根节点为黑色
3若节点为红,其子节点必为黑色 :新增节点的父节点必须为黑
4任一节点至NULL(树尾端)的任何路径,所含黑节点之数必须相同 :新增节点必为红(把其当为子节点)
注意,并没有说明若节点为黑,子节点为红,如果是这样就变成红黑相间了
4种插入情形:
1) S为黑,且X为外侧插入:单旋P,G,再更改P,G颜色
2) S为黑,且X为内侧插入:单旋P,G,更改G,X颜色,再将结果对G单旋,
3) S为红,且X为外侧插入,且GG为黑:单旋P,G,更改X的颜色
4) S为红,且X为外侧插入,且GG为红:单旋P,G,更改X的颜色,持续上述过程,直至不再有父子连续为红情况
解决4)连续上行调整的方法:采用由上而下程序:
思路:设新增节点为A,沿着A的路径,只要看到有某节点X的两个子节点都为红色,就把X改为红色,并把两个子节点改为黑色。
RB-tree:使用双层节点结构和双层迭代器结构。
_rb_tree_node继承自_rb_tree_node_base,_rb_tree_iterator继承自_rb_tree_base_iterator
RB_tree迭代器:
性质:双向迭代器,但不能随机存取
RB_tree构造方式:
1) 复制现有红黑树产生新的红黑树
2) 产生空树
RB_tree插入方式:
1) insert_equal:插入新值,节点键值允许重复
2) insert_unique:插入键值必须唯一
下面是红黑树部分重要函数的实现
#include<iostream>
#include<string>
#include<vector>
#include<iterator>
using namespace std;
typedef bool _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_type color_type;
typedef _rb_tree_node_base* base_ptr;
color_type color;//节点颜色,非红即黑
base_ptr parent;//父节点指针
base_ptr left;//左孩子指针
base_ptr right;//右孩子指针
//一直向左走,获取最小值节点
static base_ptr minimun(base_ptr x)
{
while(x->left!=0)
{
x = x->left;
}
return x;
}
//一直向右走,获取最大值节点
static base_ptr maxmimum(base_ptr x)
{
while(x->right!=0)
{
x = x->right;
}
return x;
}
};
//红黑树派生类节点
template<typename Value>
struct _rb_tree_node : public _rb_tree_node_base
{
typedef _rb_tree_node<Value>* link_type;
Value value_field;//节点值
};
//红黑树基类迭代器
struct _rb_tree_base_iterator
{
typedef _rb_tree_node_base::base_ptr base_ptr;
typedef bidirectional_iterator_tag iterator_category;
typedef ptrdiff_t difference_type;
base_ptr node;//用来与容器之间产生连接关系
void increment()
{
if(0!=node->right)//如果有右孩子
{
node = node->right;//向右走
while(0!=node->left)//一直走到该右孩子的左子树底部
{
node = node->left;
}
}
else//没有右孩子
{
base_ptr p = node->parent;//找到父节点
while(node==p->right)//如果当前节点为父节点的右孩子
{
node = p;//一直向上寻找,直到当前节点不是父节点的右孩子
p = node->parent;
}
//特殊情形:寻找根节点的下一节点,而根节点无右节点
if(node->right!=p)//如果此时的右子节点不等于此时的父节点。
{
node = p;//则此时的父节点即为下一个要访问的对象
}
//否则此时的node就是下一个要访问的对象
}
}
void decrement()
{
//如果是红节点且父节点的父节点为自己(节点为头节点或尾节点),则右节点就是退一步要访问的对象
if(node->color==_rb_tree_red && node->parent->parent==node)
{
node = node->right;
}
//如果有左孩子,上一个访问的节点是为左孩子的右子树的底部
else if(0!=node->left)//如果有左孩子
{
base_ptr p = node->left;
while(0!=p->right)
{
p = p->right;
}
node = p;
}
//既不是根节点,也没有左孩子,则向上追溯到当前节点不是父节点的左节点时,该节点的父节点就上上一个访问的节点
else
{
base_ptr p = node->parent;
while(node==p->left)
{
node = p;
p = p->parent;
}
node = p;
}
}
};
//红黑树派生类迭代器
template<typename Value,typename Ref,typename Ptr>
struct _rb_tree_iterator : public _rb_tree_base_iterator
{
//为各个类型起别名
typedef Value value_type;
typedef Ref reference;
typedef Ptr pointer;
typedef _rb_tree_iterator< Value,Value&,Value* > iterator;
typedef _rb_tree_iterator< Value,const Value&,const Value*> const_iterator;
typedef _rb_tree_iterator< Value,Ref,Ptr> self;//?为什么要有这个
typedef _rb_tree_node<Value>* link_type;
_rb_tree_iterator(){}
_rb_tree_iterator(link_type x){node=x;}
_rb_tree_iterator(const_iterator& it){node = it.node;}
reference operator*() const{return link_type(node)->value_field;}
#ifdef _SGI_STL_NO_ARROW_OPERAATOR
pointer operator->() const {return &(operator*());}
#endif
self ++operator++() {increment();return *this;}
self operator++(int){self temp = *this;increment();return temp;}
operator--();
operator--(int);
};
//红黑树类
template<class Key,class Value,class KeyOfValue,class Compare,class Alloc>
class rb_tree
{
protected:
typedef void* void_pointer;
typedef _rb_tree_node_base* base_ptr;
typedef _rb_tree_node<Value> rb_tree_node;
typedef simple_alloc<rb_tree_node,Alloc> rb_tree_node_allocator;
typedef _rb_tree_color_type color_type;
public:
typedef Key key_type;
typedef Value value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef const value_type& reference;
typedef const const value_type& const_reference;
typedef _rb_tree_node* link_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
protected:
link_type get_node(){return _rb_tree_node_allocator::allocate();}
void put_node(link_type p){rb_tree_node_allocator::deallocate(p);}
link_type create_node(const value_type& x)
{
link_type temp = get_node();//分配空间
_STL_TRY
{
construct(&temp->value_field,x);//构造内容
}
_STL_UNWIND(put_node(temp));
return temp;
}
//复制一个节点(值与颜色)
link_type clone_node(link_type)
{
link_type temp = create_node(x->value_field);
temp->color = x->color;
temp->right = 0;
temp->left = 0;
return temp;
}
void destry_node(link_type x)
{
destroy(&x->value_field);//析构内容
put_node(p);//释放内存
}
protected:
size_type node_count;//树的大小=节点数量
link_type header;
Compare key_compare;
//取得header成员
link_type& root() const {return (link_type&)header->parent;}
link_type& leftmost() const {return (link_type&)header->left;}
link_type& rightmost() const {return (link_type&)header->right;}
//取得节点x的成员
static link_type& left(link_type x){return (link_type)x->left;}
static link_type& right(link_type x){return (link_type)x->right;}
static link_type& parent(link_type x){return (link_type)x->parent;}
static reference value(link_type x){return x->value_field;}
static const Key& key(link_type x){return KeyOfValue()value(x);}//?
static color_type& color(link_type x){return (color_type&)x->color;}
private:
//header节点是根节点的父节点
void init()
{
header = get_node();//产生节点空间,令header指向它
color(header) = _rb_tree_red;//令header为红色,区分root
root() = 0;
leftmost() = header;//令header左孩子为自己
rightmost() = header;//令header右孩子为自己
}
public:
//作用:插入节点,节点键值允许重复。返回值:红黑树的迭代器,指向新节点
typename rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::iterator
insert_equal(const Value& v)
{
link_type y = header;
link_type x = root;
while(0!=x)
{
y = x;
x = key_compare(KeyOfValue()(v),key(x)?left(x):right(x));//遇大往左,否则往右
}
return _insert(x,y,v);//x为插入节点,y为插入节点的父节点,v为键值
}
//作用:插入节点,节点键值不允许重复。返回:是一个pair,第一个元素为红黑树的迭代器,指向新节点,第二元素表示插入成功与否
pair< typename rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::iterator,bool>
insert_unique(const Value& v)
{
link_type y = header;
link_type x = root();//从根节点开始
bool comp = true;
while(0!=x)//从根节点往下寻找插入点
{
y = x;
comp = key_compare(KeyOfValue()(v),key(x));//v的键值与当前节点键值进行比较
x = comp ? left(x) : right(x);//v的键值<=当前节点键值,则向左
}
//此时y必为插入节点的父节点
iterator j = iterator(y);//令迭代器指向插入节点的父节点
if(comp)//如果v的键值>当前节点键值,则向右
{
if(begin()==j)//若插入节点的父节点为最左节点
{
return pair<iterator,bool>(_insert(x,y,v),true);
}
else//插入节点的父节点不为最左节点
{
--j;//调整迭代器,回头准备测试
}
if(key_compare(Key(j.node),KeyOfValue()(v)))//如果J的键值>当前节点键值,则向右
{
return pair<iterator,bool>(_insert(x,y,v),true);
}
//如果走到这里,表示键值重复
return pair<iterator,bool>(j,false);
}
}
//真正的插入执行程序
typename rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::iterator
_insert(base_ptr x_,base_ptr y_,const Value& v)
{
link_type x = (link_type)x_;
link_type y = (link_type)y_;
link_type z;
if(y==header || x!=0 || key_compare(KeyOfValue()(v),key(y)))
{
z = create_node(v);//产生新节点
left(y) = z;//当y为根节点的父节点时,leftmost()=z
if(y==header)
{
root() = z;
rightmost() = z;
}
else if(leftmost()==y)//如果y为最左节点 ?
{
leftmost() = z;//维护leftmost(),使它永远指向最左节点
}
else
{
z = create_node(v);//产生新节点
right(y) = z;//令新节点成为插入节点父节点的右孩子
if(rightmost()==y)
{
rightmost() = z;//维护rightmost(),使它永远指向最右节点
}
}
//设定新节点的父节点和左右孩子
parent(z) = y;
left(z) = 0;
right(z) = 0;
_rb_tree_reblance(z,header->parent);//传入新增节点和根节点进行平衡处理
++node_count;
return iterator(z);//返回迭代器,指向新节点
}
}
}
int main(int argc,char *argv[])
{
cout<<"红黑树的原理"<<endl;
getchar();
return 0;
}