红黑树增删操作的代码实现(上)
2013-07-24 14:58
204 查看
这几天一直在学习红黑树,由于是第一次接触,所以刚开始觉得挺麻烦的,经过这几天的各种google,终于对其的插入和删除操作有了一定了解,现在就分享下:
红黑树的定义:红黑树是每个节点都带有颜色属性的二叉查找树,颜色为红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:
性质1. 节点是红色或黑色。
性质2. 根是黑色。
性质3. 所有叶子都是黑色(叶子是NIL节点)。
性质4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点。
性质5. 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。
首先是红黑树的结构定义:红黑树定义为一个拥有5个属性的结构体:
在实现红黑树的插入操作时,首先要实现树的旋转操作,这在插入删除操作之后调整红黑树时要用到,分为左旋和右旋操作,实现代码如下:
之后是红黑树的插入操作,插入操作其实和普通的二叉排序树的插入操作一样,只是在插入结点之后,红黑树的5条性质可能会被破坏,这样就需要调用调整函数对红黑树进行调整,以让其满足红黑树的5条性质,
红黑树的插入实现函数如下:
插入新结点之后,会出现如下需要调整红黑树的情况(还有几种情况没列出,因为那些情况不需要调整树)
1.当红黑树中没有结点时,新结点直接涂黑就可以了。
2.新结点的父亲结点为红色,并且新结点的叔叔结点也为红色
调整方法:父=>黑;叔=>黑;祖=>红;往上遍历
3.新结点的父结点为红色,叔叔结点为黑色,新结点为其父结点的左孩子
调整方法:父=>黑;祖=>红;祖父右旋转;
4.新结点的父结点为红色,叔叔结点为黑色,新结点为其父结点的右孩子
调整方法:新=>黑;祖=>红;父左旋转;祖右旋转
具体的实现代码如下所示:
红黑树的定义:红黑树是每个节点都带有颜色属性的二叉查找树,颜色为红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:
性质1. 节点是红色或黑色。
性质2. 根是黑色。
性质3. 所有叶子都是黑色(叶子是NIL节点)。
性质4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点。
性质5. 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。
首先是红黑树的结构定义:红黑树定义为一个拥有5个属性的结构体:
typedef struct RBTNode{ int color; struct RBTNode *parent; struct RBTNode *left; struct RBTNode *right; int value; }RBTNode,*RBTree;
在实现红黑树的插入操作时,首先要实现树的旋转操作,这在插入删除操作之后调整红黑树时要用到,分为左旋和右旋操作,实现代码如下:
//右旋操作实现代码 void RIGHT_ROTATE(RBTree T,RBTree x) { RBTree y; y = x->left; x->left = y->right; if(y->right!=nil) { y->right->parent = x; } y->parent = x->parent; if(x->parent == nil) { root = y; } else if(x->parent->left == x) { x->parent->left = y; } else { x->parent->right = y; } y->right = x; x->parent = y; } //左旋操作实现代码,与右旋操作一样 void LEFT_ROTATE(RBTree T,RBTree x) { RBTree y; y = x->right; x->right =y->left; if(y->left!=nil) { y->left->parent = x; } y->parent = x->parent; if(x->parent == nil) { root = y; } else if(x == x->parent->left) { x->parent->left = y; } else { x->parent->right = y; } y->left = x; x->parent = y; }左旋和右旋操作原理比较简单,看代码就能理解。
之后是红黑树的插入操作,插入操作其实和普通的二叉排序树的插入操作一样,只是在插入结点之后,红黑树的5条性质可能会被破坏,这样就需要调用调整函数对红黑树进行调整,以让其满足红黑树的5条性质,
红黑树的插入实现函数如下:
//插入操作,这与一般的二叉排序树的插入操作类似 void RBTreeInsert(RBTree T,RBTree z) { RBTree x,y; y = nil; x = root; while(x!=nil) { y = x; if(z->value<x->value) { x = x->left; } else { x = x->right; } } z->parent = y; if(y == nil) { root = z; } else if(z->value<y->value) { y->left = z; } else { y->right = z; } z->left = nil; z->right = nil; z->color = RED; RBTreeInsertFixup(T,z); }在将结点插入到红黑树的相应位置之后,将新结点涂红(如果涂黑,就会导致根到叶子的路径上有一条路上,多了一个额外的黑结点,这个是很难调整的。但涂红后可能会导致出现两个连续的红色结点的冲突,那么可以通过颜色调整和树旋转来调整)。
插入新结点之后,会出现如下需要调整红黑树的情况(还有几种情况没列出,因为那些情况不需要调整树)
1.当红黑树中没有结点时,新结点直接涂黑就可以了。
2.新结点的父亲结点为红色,并且新结点的叔叔结点也为红色
调整方法:父=>黑;叔=>黑;祖=>红;往上遍历
3.新结点的父结点为红色,叔叔结点为黑色,新结点为其父结点的左孩子
调整方法:父=>黑;祖=>红;祖父右旋转;
4.新结点的父结点为红色,叔叔结点为黑色,新结点为其父结点的右孩子
调整方法:新=>黑;祖=>红;父左旋转;祖右旋转
具体的实现代码如下所示:
void RBTreeInsertFixup(RBTree T,RBTree z) { RBTree y; while(z->parent->color == RED)//这时说明z肯定存在父结点和祖父结点 { if(z->parent == z->parent->parent->left)//如果z的父结点为祖父结点的左孩子 { y = z->parent->parent->right;//y为z的叔叔结点 if(y->color == RED)//情况1:红叔情况 {//将父结点和叔叔结点涂黑,祖父结点涂红 z->parent->color = BLACK; y->color = BLACK; z->parent->parent->color = RED; z = z->parent->parent;//调整之后将祖父结点作为调整对象 } else { if(z == z->parent->right)//z是父结点的右孩子 {//情况2:黑叔,新结点z为右孩子 z = z->parent; LEFT_ROTATE(T,z); } //通过上面两部操作将情况2转为情况3,然后两种情况一起操作 //情况3:黑叔,z为右孩子 z->parent->color = BLACK; z->parent->parent->color = RED; RIGHT_ROTATE(T,z->parent->parent); } } else//如果父结点为祖父结点的右孩子 { y = z->parent->parent->left;//y为z的叔叔结点 if(y->color == RED)//情况1:红叔 {//将父结点和叔叔结点涂黑,祖父结点涂红 z->parent->color = BLACK; y->color = BLACK; z->parent->parent->color = RED; z = z->parent->parent;//调整之后将祖父结点作为调整对象 } else { if(z == z->parent->left)//z为父结点的左孩子 {//情况2:黑叔,新结点为左孩子 z = z->parent; RIGHT_ROTATE(T,z); } //情况3:黑叔,新结点为右孩子 z->parent->color = BLACK; z->parent->parent->color = RED; LEFT_ROTATE(T,z->parent->parent); } } } root->color = BLACK;//包含情况:z为唯一的结点的情况 }
相关文章推荐
- 红黑树插入操作分析及代码实现
- Java语言实现对MySql数据库中数据的增删改查操作的代码
- javascript Xml增删改查(IE下)操作实现代码
- PHP程序中使用PDO对象实现对数据库的增删改查操作的示例代码
- 用jquery代码实现表格行列的增删操作(每行编号随之修改)
- GridView绑定SqlDataSource以其自带功能实现增删查改等操作(不写后台代码)一
- php中操作memcached缓存进行增删改查数据的实现代码
- php中操作memcached缓存进行增删改查数据的实现代码
- javascript Xml增删改查(IE下)操作实现代码
- PHP程序中使用PDO对象实现对数据库的增删改查操作的示例代码
- 文本编辑器 “查找与替换”操作的“全部替换”功能的实现代码 Visual Basic 2005 编写
- php类自动装载、链式操作、魔术方法实现代码
- asp.net编程中实现导入xls表格操作的实现代码
- Jedis-缓存操作具体实现代码。
- 数据结构之队列的基本操作入队出队初始化删除-c++代码实现及运行实例结果
- Python中的文件和目录操作实现代码
- Python中的文件和目录操作实现代码
- json的前台操作和后台操作实现代码
- 对xml增删改查操作的实现
- 队列的基本操作概念及各种实现方式的代码