1.定义
红黑树是一种二叉查找树,每一个节点增加一个存储位表示节点的颜色,可以是黑或红。通过对任何一条从根到叶子的路径上的各个节点着色方式的限制,红黑树确保没有一条路径会比其他路径长两倍,是一种弱平衡二叉树,相对于要求严格的AVL树来说,他的旋转次数少,对于搜索,插入,删除操作较多的情况下,通常使用红黑树。
2.性质:
每个节点非黑即红
根节点是黑的
每个叶节点(树尾端)都是黑的
如果一个节点是红色的,则他的字节的必须是黑的
对于任意节点而言,其叶子结点树NULL指针的每条路径都包含相同数目的黑节点
在o(log n)时间内做查找,插入,删除
从根到叶子的最长可能路径不多于最短的可能路径的两倍长
3.实际使用
STL中map和set的底层,
epoll的文件系统中,
伙伴关系中内存的平衡,
linux中进程的调度用的是红黑树
epoll的底层是用红黑树和双向链表实现的,epoll_create()系统调用在内核中创建一个eventpoll类型的句柄,包括rbtree的根节点和双向链表的头结点,然后通过epoll_ctl()系统调用,向epoll对象的红黑树结构中添加,删除修改,返回0标识成功,返回-1表示失败。最后通过epoll_wait()系统调用判断双向链表是否为空,空则阻塞。文件描述符状态改变,fd上的毁掉函数被调用,该函数将fd加入双向链表,此时epoll_wait函数被唤醒,返回就绪好的实践。
4.代码实现
#include<iostream>
using namespace std;
typedef enum {RED=0,BLACK=1} ColorType;
typedef int KeyType;
typedef struct rb_node
{
rb_node* leftchild;
rb_node* parent;
rb_node* rightchild;
ColorType color;
KeyType key;
}rb_node,*RBTree;
rb_node* BuyNode();
static rb_node* Nil = BuyNode();
rb_node* BuyNode()
{
rb_node* s = (rb_node*)malloc(sizeof(rb_node));
if (nullptr == s) exit(1);
memset(s, 0, sizeof(rb_node));
s->color = RED;
s->leftchild = Nil;
s->rightchild = Nil;
return s;
}
rb_node* Buynode(KeyType kx)
{
rb_node* s = (rb_node*)malloc(sizeof(rb_node));
if (nullptr == s) exit(1);
memset(s, 0, sizeof(rb_node));
s->key = kx;
return s;
}
//左单旋
//1.2.3步,是旋转时 的思路,(a,b,c)是改写parent指针的指向
void RotateLeft(rb_node*& tree, rb_node* ptr)
{
rb_node* newroot = ptr->rightchild;//1
newroot->parent = ptr->parent;//a
ptr->rightchild = newroot->leftchild;//2
if (newroot->leftchild != nullptr)//排除12,23,34,这种
{
newroot->leftchild->parent = ptr;//b
}
newroot->leftchild = ptr;//3
//是根
if (ptr == tree) tree = newroot;
else
{
if (ptr->parent->leftchild == ptr)
{
ptr->parent->leftchild = newroot;
}
else
{
ptr->parent->rightchild = newroot;
}
}
ptr->parent = newroot;//c
}
//右单旋转
void RotateRight(rb_node*& tree,rb_node* ptr)
{
rb_node* newroot = ptr->leftchild;
newroot->parent= ptr->parent ;
ptr->leftchild = newroot->rightchild;
if (newroot->rightchild != nullptr)
{
newroot->rightchild->parent = ptr;
}
newroot->rightchild = ptr;
if (ptr == tree) tree = newroot;
else
{
if (ptr->parent->leftchild == ptr)
{
ptr->parent->leftchild = newroot;
}
if (ptr->parent->rightchild == ptr)
{
ptr->parent->rightchild = newroot;
}
}
ptr->parent = newroot;
}
void PassRBTree(rb_node*& tree, rb_node* p)
{
rb_node* _X = nullptr;
for (; p != tree && p->parent->color==RED;)
{
if (p->parent->parent->rightchild == p->parent)
{
if (p->parent->parent->rightchild == p->parent)
{
_X = p->parent->parent->leftchild;
if (_X->color == RED)
{
_X->color = BLACK;
p->parent->color = BLACK;
p->parent->parent->color = RED;
p = p->parent->parent;
}
else
{
if (p->parent->leftchild == p)
{
p = p->parent;
RotateRight(tree, p);
}
p->parent->color = BLACK;
p->parent->parent-> color = RED;
RotateLeft(tree, p->parent->parent);
}
}
}
}
}
rb_node* MakeRoot(KeyType kx)
{
rb_node* root = BuyNode();
root->color = BLACK;
root->key = kx;
return root;
}
bool Insert(rb_node*& root, KeyType key)
{
if (root== nullptr)
{
root= MakeRoot(key);
return true;
}
rb_node* pa = nullptr;
rb_node* p = root;
while (p != nullptr && p->key !=key)
{
pa = p;
p = key < p->key ? p->leftchild : p->rightchild;
}
if (p != nullptr && p->key == key) return false;
p = Buynode(key);
p->parent = pa;
if (key < pa->key)
{
pa->leftchild = p;
}
else
{
pa->rightchild = p;
}
PassRBTree(root, p);
return true;
return true;
}