数据结构与算法复习
1.1.1 红黑树
红黑树用在哪里?
a.hashmap
b.cfs
c.epoll
d.定时器
e.nginx
关键存在于 [key,value] 结构,强调查找。
(强查找的过程有:
1,红黑树
2,hash
3,b/b+tree
4,跳表)
首先:红黑树就是一种平衡的二叉查找树,具体具有下列五条特性:
1.节点是红色或者黑色
2.根节点是黑色
3.每个叶子的节点都是黑色
4.每个红色节点的两个子节点都是黑色的。
5.从任意节点到其每个叶子的所有路径都包含相同的黑色节点。
代码实现:
1.结点定义
typedef struct _rbtree_node
{
//颜色
unsigned char color;
struct _rbtree_node *right;
struct _rbtree_node *left ;
struct _rbtree_node *parent ;
int key;
void *value;
}rbtree_node;
2.红黑树定义
typedef struct _rbtree
{
struct _rbtree_node *root;
//所有叶子结点都为黑,那就让他们都指向同一个结点
struct _rbtree_node *nil;
}rbtree;
缺点:
1)key的类型写死了
2)可复用性差
改进代码:
typedef int KEY_TYPE;
//定义宏
//简化节点结构的创建
#define RBTREE_ENTRY(name,type)\
struct name{\
unsigned char color;\
struct type *right;\
struct type *left ;\
struct type *parent ;\
}
typedef struct _rbtree_node
{
//颜色
KEY_TYPE key;
void *value;
#if 0
struct _rbtree_node *right;
struct _rbtree_node *left ;
struct _rbtree_node *parent ;
unsigned char color;
#else
//使用宏可简单,多次定义多颗红黑树
RBTREE_ENTRY(,_rbtree_node) thr_ready;
RBTREE_ENTRY(,_rbtree_node) thr_wait;
RBTREE_ENTRY(,_rbtree_node) thr_wait;
RBTREE_ENTRY(,_rbtree_node) thr_exit;
#endif
}rbtree_node;
typedef struct _rbtree
{
struct _rbtree_node *root;
//所有叶子结点都为黑,那就让他们都指向同一个结点
struct _rbtree_node *nil;
}rbtree;
红黑树的左旋与右旋
左旋代码实现
//左旋
void rbtree_left_rotate(rbtree *T,rbtree_node *x){
//传入 *T目的是为了:1.判断左子树或右子树是否为叶子结点 2.判断父结点是否为根结点
rbtree_node *y = x -> right;
//第一对
x->right = y -> left;
if( y->left!= T->nil) y->left->parent = x;
y->parent = x -> parent;
//第二对
if(x->parent==T->nil){
T->root = y;
}else if(x == x->parent->left){
x->parent->left = y;
}else{
x->parent->right = y;
}
//第三对
y -> left = x;
x -> parent = y;
}
右旋代码实现(将左旋中,x和y互换,left和right互换)
//右旋
void rbtree_right_rotate(rbtree *T,rbtree_node *y){
//传入 *T目的是为了:1.判断左子树或右子树是否为叶子结点 2.判断父结点是否为根结点
rbtree_node *x = y -> left;
//第一对
y->left = x-> right;
if( x->right!= T->nil) x->right->parent = y;
//第二对
x->parent = y -> parent;
if(y->parent==T->nil){
T->root = x;
}else if(y == y->parent->right){
y->parent->right = x;
}else{
y->parent->left = x;
}
//第三对
x-> right = y;
y-> parent = x;
}
红黑树的插入
//调整红黑树
void rbtree_insert_fixup(rbtree *T,rbtree_node *z){
//z是插入的结点,一定是红色的
//z是红色
//z的父结点是红色
//z的祖父结点是黑色
//z的叔父结点不知道 **
while(z->parent->color== 'r')//如果父结点的红色,必须调整
{
if(z->parent == z->parent->parent->left)
{
rbtree_node *y = z->parent->parent->right;
if(y->color == 'r'){
z->parent->color = 'b';
z->parent->parent->color = 'r';
y->color = 'b';
z = z->parent->parent;
}else{//y是黑色的
if(z == z->parent->right)
{
z = z->parent;
rbtree_left_rotate(T,z);
}
z->parent->color = 'b';
z->parent->parent->color = 'r';
rbtree_right_rotate(T,z->parent->parent);
}
}else{
}
}
}
//插入
//插入的结点是红色的,这样才不改变红黑树的性质
void rbtree_insert(rbtree *T,rbtree_node *z)
{
rbtree_node *x = T->root;
rbtree_node *y = T->nil;
while(x!=T->nil)
{
//y比x高一级
//最后x会指向叶子(nil),而y就是我们要操作的结点
y = x;
if(z->key < x->key){
x = x -> left;
}else if(z->key > x -> key){
x = x -> right;
}else{
//Exit
return ;
}
}
if(y==T->nil) T->root = z;
else{
if(y->key > z->key){
y->left = z;
}else{
y->right = z;
}
}
z->parent = y;
z->left = T->nil;
z->right = T->nil;
z->color = 'r';
}
课后作业:了解红黑树的应用
1.epoll事件管理怎么做的
2.Linux进程调度CFS
3.Nginx Timer事件管理