1.5 RB树的操作
红黑树的最主要特征,在于其颜色满足特定的性质。普通的节点添加,极有可能破坏红黑树的性质,所以在添加红黑树节点时,需要将整个红黑树的颜色进行调整。
在理解插入、删除操作之前要先理解两个函数,即红黑树的左旋和右旋。
左旋和右旋都是为了保证平衡二叉树的性质不变,即是通过左旋和右旋来保证红黑二叉树的第五条性质满足。红黑二叉树的添加跟普通的二叉树的添加类似。不过在添加节点后需要对节点的颜色进行调整,甚至对树的结构进行调整,来满足红黑树的性质。
1.5.1左旋
对照下图可以更好的理解下面的程序。将node设置为pivot,root为根。
//记住设置节点的左右孩子后,还要设置节点的parent
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) { -------------------------------------------------------------------------(1) struct rb_node *right = node->rb_right; //取node节点的右节点,right= Y struct rb_node *parent =rb_parent(node); //取node节点的父节点,parent= P ---------------------------------------------------------------------------(2) if((node->rb_right = right->rb_left)) //注意是 = 而非==,pivot的右子设置为P的左子即//pivot->rb_right= b rb_set_parent(right->rb_left, node); //同时将b->parent设置为pivot ----------------------------------------------------------------------------(3) right->rb_left = node; //将pivot设置为Y的左子 rb_set_parent(right, parent); //设置Y的parent为P ----------------------------------------------------------------------------(4) if (parent) { if (node ==parent->rb_left) //如果pivot为P的左子 parent->rb_left =right; //则P的右子设置为Y else parent->rb_right =right;// 否则P的左子设置为Y } else root->rb_node = right; //如果P为空,即pivot(node)为根节点,旋转//后,Y变为根 rb_set_parent(node, right); //设置pivot的parent为Y }
1.5.2右旋
对照下图可以更好的理解下面的程序。将node设置为pivot,root为根。
static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) { -----------------------------------------------------------(1) struct rb_node *left = node->rb_left; //取pivot节点的左节点,left= Y struct rb_node *parent =rb_parent(node); //取pivot节点的父节点,parent = P -----------------------------------------------------------(2) if((node->rb_left = left->rb_right)) // 如果Y不为空,设置pivot的左子为Y的右子 rb_set_parent(left->rb_right,node);//设置c的父亲节点为pivot -----------------------------------------------------------(3) left->rb_right = node; //设置Y的右节点为pivot rb_set_parent(left,parent); //设置Y的父亲节点为P -----------------------------------------------------------(4) if (parent) { if (node ==parent->rb_right) // 旋转,设置pivot的原左节点为P的右孩子 parent->rb_right = left; else parent->rb_left = left; } else root->rb_node =left; rb_set_parent(node, left); //设置pivot的父亲节点 }
(未完待续。。。)