红黑树(Red BlackTree)的实现
2012-09-04 12:41
591 查看
前面我们讲解了简单二叉查找树、AVL树,伸展树,对于一棵高度为h的二叉查找树,其动态集合操作Search、Minimum、Maximum、Successor、Predecessor、Insert、Delete的运行时间为θ(h),树的高度决定了在树上操作的成本。
一些常见的搜索树的高度:
平衡二叉搜索树:O(lgn)
1962年提出的AVL树:<=1.44lgn
1972年提出的红黑树:<=2lg(n+1)
红黑树是通过对二叉查找树结点上增加一个存储位表示结点的颜色(红色或黑色) 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,确保没有一条路径会比其他路径长出两倍,从而接近平衡。
一、红黑树的性质
1、红黑树的定义
红黑树是满足如下性质的二叉查找树:
(1) 每个结点必须为红色或黑色。
(2) 根为黑色。
(3) 树中的nil叶子为黑色。
(4) 若结点为红,则其两个子孩子必为黑。
(5) 对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点。
2、黑高度
从某个结点x出发(不包括该结点)到达一个叶结点的任意一条路径上,黑色结点的个数称为该结点x的黑高度,用bh(x)表示。
3、红黑树的黑高度
红黑树的黑高度定义为其根结点的黑高度,记为bh(root[T]).。
4、红黑树的高度
一棵含n个内结点的红黑树的高度至多为2lg( n+1) 。(证明请看算法导论)
二、红黑树的实现
1、原理请看参考资料[1]、[2]、[3]
2、下面给出的C++实现是完全按照算法导论上的伪代码来的。参考资料[4]中给出了自顶向下红黑树的部分实现(未提供删除操作),采用的是不含父节点指针的结点结构,但是实现复杂,不是很好理解。
3、实现代码
参考资料:
[1]算法导论(第2版)第13章P163-P176
[2]红黑树及扩张:http://wenku.baidu.com/view/673d3e6eb84ae45c3b358c29.html
[3]博客文章(C#实现):/content/3959184.html
[4]Data Structures and Algorithm Analysis in C++(third editon) (数据结构与算法分析C++描述,第3版 )
[5]文章(C++实现):http://www.linuxidc.com/Linux/2012-01/52530.htm
[6]文章(C实现):http://www.chinaunix.net/old_jh/23/1308846.html
[7]C语言实现:http://wenku.baidu.com/view/1187190390c69ec3d5bb7544.html
[8]红黑树的实现与讨论:http://www.cppblog.com/daly88/archive/2009/11/20/101519.html
一些常见的搜索树的高度:
平衡二叉搜索树:O(lgn)
1962年提出的AVL树:<=1.44lgn
1972年提出的红黑树:<=2lg(n+1)
红黑树是通过对二叉查找树结点上增加一个存储位表示结点的颜色(红色或黑色) 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,确保没有一条路径会比其他路径长出两倍,从而接近平衡。
一、红黑树的性质
1、红黑树的定义
红黑树是满足如下性质的二叉查找树:
(1) 每个结点必须为红色或黑色。
(2) 根为黑色。
(3) 树中的nil叶子为黑色。
(4) 若结点为红,则其两个子孩子必为黑。
(5) 对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点。
2、黑高度
从某个结点x出发(不包括该结点)到达一个叶结点的任意一条路径上,黑色结点的个数称为该结点x的黑高度,用bh(x)表示。
3、红黑树的黑高度
红黑树的黑高度定义为其根结点的黑高度,记为bh(root[T]).。
4、红黑树的高度
一棵含n个内结点的红黑树的高度至多为2lg( n+1) 。(证明请看算法导论)
二、红黑树的实现
1、原理请看参考资料[1]、[2]、[3]
2、下面给出的C++实现是完全按照算法导论上的伪代码来的。参考资料[4]中给出了自顶向下红黑树的部分实现(未提供删除操作),采用的是不含父节点指针的结点结构,但是实现复杂,不是很好理解。
3、实现代码
#include <cstdlib> #include <iostream> using namespace std; template <typename Comparable> class RBTree { public: RBTree() { nil = new RBTreeNode;//哨兵结点为黑色 nil->parent = nil; nil->lchild = nil; nil->rchild = nil; root = nil; } ~RBTree() { makeEmpty(root); delete nil; } void preOrderTraverse()const { preOrderTraverse(root); } void inOrderTraverse()const { inOrderTraverse(root); } void printTree()const { cout<<"preOrder :"<<endl; preOrderTraverse(); cout<<endl; cout<<"inOrder :"<<endl; inOrderTraverse(); cout<<endl<<endl; } //将元素插入红黑树中 bool insert(const Comparable& elem) { RBTreeNode* y = nil; //y记录当前结点的父结点 RBTreeNode* x = root; //从根结点开始扫描,寻找插入点 while(x != nil) { y = x; if(elem < x->data) //当前结点左子树中继续扫描 { x = x->lchild; } else if(x->data < elem) { x = x->rchild; //当前结点右子树中继续扫描 } else { return false; //树中已存在该元素 } } //准备插入该元素 RBTreeNode* z = new RBTreeNode(elem); z->parent = y; //y是z的双亲 if(y == nil) //z插入空树 { root = z; //z为新的根结点 } else if(elem < y->data) { y->lchild = z; //z为y的左孩子 } else { y->rchild = z; //z为y的右孩子 } z->lchild = nil; z->rchild = nil; z->color = RED; insertFixup(z); //插入后调整 return true; } //从红黑树中删除一个元素 bool remove(const Comparable& elem) { RBTreeNode* z = search(elem, root);//查找结点 RBTreeNode* y; //y为要删除的结点 RBTreeNode* x; //y的孩子结点 if(z != nil) { if(z->lchild == nil || z->rchild == nil)//case1 2 { y = z; } else //左右子树均不空 case 3 { y = successor(z);//后继y的左子树必然为空(nil) } //确定y的孩子结点(待连接到p[y]) if(y->lchild != nil) { x = y->lchild; } else { x = y->rchild; } x->parent = y->parent; if(y->parent == nil)//y为根结点 { root = x; } else if(y == y->parent->lchild) { y->parent->lchild = x; } else { y->parent->rchild = x; } if(y != z)//case 3 { z->data = y->data; } if(y->color == BLACK)//删除结点为黑色,重新调整 { removeFixup(x); } delete y; return true; } return false; //树中不存在该结点 } bool search(const Comparable& elem)const { if(search(elem, root)!= nil) { return true; } return false; } bool isEmpty() { return root == nil; } /*求某一元素的后继,前驱类似 *应该确保树非空,且树中存在该元素 否则抛出异常(这里不做处理) */ Comparable successor(const Comparable& elem) { RBTreeNode* z = search(elem, root);//查找结点 if(z != nil) { return z->data; } // else // { // throw exception; // } } private: enum COLOR{BLACK,RED}; struct RBTreeNode { COLOR color; //结点颜色 Comparable data; //结点数据 struct RBTreeNode* parent; //父节点指针 struct RBTreeNode* lchild; //左孩子结点指针 struct RBTreeNode* rchild; //右孩子结点指针 RBTreeNode(): color(BLACK),data(Comparable()), parent(NULL),lchild(NULL),rchild(NULL){} RBTreeNode(const Comparable& elem ): color(BLACK),data(elem), parent(NULL),lchild(NULL),rchild(NULL){} }; //======================================== RBTreeNode * root; //根结点 RBTreeNode * nil; //哨兵结点 //======================================== void leftRotate(RBTreeNode* x) //左旋 { RBTreeNode* y = x->rchild; x->rchild = y->lchild; if(y->lchild != nil) { y->lchild->parent = x; } y->parent = x->parent; if(x->parent == nil) { root = y; //y为新的根结点 } else if(x == x->parent->lchild) { x->parent->lchild = y; } else { x->parent->rchild = y; } y->lchild = x; x->parent = y; } void rightRotate(RBTreeNode* x)//右旋 { RBTreeNode* y = x->lchild; x->lchild = y->rchild; if(y->rchild != nil) { y->rchild->parent = x; } y->parent = x->parent; if(x->parent == nil) { root = y; } else if(x == x->parent->lchild) { x->parent->lchild = y; } else { x->parent->rchild = y; } y->rchild = x; x->parent = y; } //插入之后的修复操作 void insertFixup(RBTreeNode* z) { RBTreeNode* y; //y是z的叔父结点 while(z->parent->color == RED) { //z的父结点是z的祖父结点的左孩子 if(z->parent == z->parent->parent->lchild) { //case 1 2 3 y = z->parent->parent->rchild; if(y->color == RED) { //case1 z->parent->color = BLACK; y->color = BLACK; z->parent->parent->color = RED; z = z->parent->parent; } else //case2 or case 3 ,y->color == BLACK { //case2 if(z == z->parent->rchild) { z = z->parent; //z上溯至父节点 leftRotate(z); //左旋 } //case3 z->parent->color = BLACK; z->parent->parent->color = RED; rightRotate(z->parent->parent); } } else//case 4,5,6与上面对称 { y = z->parent->parent->lchild; if(y->color == RED) { //case4 z->parent->color = BLACK; y->color = BLACK; z = z->parent->parent; } else//case 5 or case 6 { //case 5 if(z == z->parent->lchild) { z = z->parent; rightRotate(z); } //case 6 z->parent->color = BLACK; z->parent->parent->color = RED; leftRotate(z->parent->parent); } } } root->color = BLACK; } //删除之后的修复操作 void removeFixup(RBTreeNode* x) { RBTreeNode* w; //x的兄弟结点 while(x != root && x->color == BLACK) { if(x == x->parent->lchild)//case1-4 { w = x->parent->rchild; if(w->color == RED) { //case1 w->color = BLACK; x->parent->color = RED; leftRotate(x->parent); w = x->parent->rchild; } //w->color == BLACK if(w->lchild->color == BLACK && w->rchild->color == BLACK) { //case 2 w->color = RED; x = x->parent;// } else { //case 3 if(w->rchild->color == BLACK)//左子为RED { w->lchild->color = BLACK; w->color = RED; rightRotate(w); w = x->parent->rchild; } //case 4 右子为RED w->color = x->parent->color; x->parent->color = BLACK; w->rchild->color = BLACK; leftRotate(x->parent); x = root; } } else//case5-8,和上面对称 { w = x->parent->lchild; if(w->color == RED) { //case 5 w->color = BLACK; x->parent->color = RED; rightRotate(x->parent); w = x->parent->lchild; } //w->color == BLACK if(w->lchild->color == BLACK && w->rchild->color == BLACK) { //case 6 w->color = RED; x = x->parent;// } else { //case 7 if(w->lchild->color == BLACK)//右子为RED { w->rchild->color = BLACK; w->color = RED; leftRotate(w); w = x->parent->lchild; } //case 8 左子为RED w->color = x->parent->color; x->parent->color = BLACK; w->lchild->color = BLACK; rightRotate(x->parent); x = root; } } } x->color = BLACK; } //在以t为根的红黑树中查找给定元素 //返回相应的结点指针 RBTreeNode* search(const Comparable& elem, RBTreeNode* t)const { while(t != nil && elem != t->data) { if(elem < t->data) { t = t->lchild; } else if(t->data < elem) { t = t->rchild; } } return t; } //求结点x的中序后继结点 RBTreeNode* successor(RBTreeNode* x) { RBTreeNode* y; if(x->rchild != nil) { y = x->rchild; while(y->lchild != nil) { y = y->lchild; } } else { y = x->parent; while(y != nil && x == y->rchild) { x = y; y = y->parent; } } return y; } //前序遍历 void preOrderTraverse(RBTreeNode* t)const { if(t != nil) { cout<<"("<<t->data<<","; t->color ? cout<<"RED" : cout<<"BLACK"; cout<<")"; preOrderTraverse(t->lchild); preOrderTraverse(t->rchild); } } //中序遍历 void inOrderTraverse(RBTreeNode* t)const { if(t != nil) { inOrderTraverse(t->lchild); cout<<"("<<t->data<<","; t->color ? cout<<"RED" : cout<<"BLACK"; cout<<")"; inOrderTraverse(t->rchild); } } //销毁红黑树 void makeEmpty(RBTreeNode* t) { if(t != nil) { makeEmpty(t->lchild); makeEmpty(t->rchild); delete t; t = NULL; } } }; int main(int argc, char *argv[]) { RBTree<int> rbtree; const int N = 6; //insert for(int i=1; i<N;i++) { rbtree.insert(i); cout<<"after insert "<<i<<":"<<endl; rbtree.printTree(); } //search cout<<"search: "<<endl; for(int i=1; i<N;i++) { cout<<"("<<i<<","<<rbtree.search(i)<<")"; } cout<<endl<<endl; //remove for(int i=1; i<N; i += 2) { rbtree.remove(i); cout<<"after remove: "<<i<<endl; rbtree.printTree(); } //search cout<<"search: "<<endl; for(int i=1; i<N;i++) { cout<<"("<<i<<","<<rbtree.search(i)<<")"; } cout<<endl<<endl; system("PAUSE"); return EXIT_SUCCESS; }
参考资料:
[1]算法导论(第2版)第13章P163-P176
[2]红黑树及扩张:http://wenku.baidu.com/view/673d3e6eb84ae45c3b358c29.html
[3]博客文章(C#实现):/content/3959184.html
[4]Data Structures and Algorithm Analysis in C++(third editon) (数据结构与算法分析C++描述,第3版 )
[5]文章(C++实现):http://www.linuxidc.com/Linux/2012-01/52530.htm
[6]文章(C实现):http://www.chinaunix.net/old_jh/23/1308846.html
[7]C语言实现:http://wenku.baidu.com/view/1187190390c69ec3d5bb7544.html
[8]红黑树的实现与讨论:http://www.cppblog.com/daly88/archive/2009/11/20/101519.html
相关文章推荐
- 红黑树与C实现算法 - RedBlackTree.c
- 红黑树(red black tree)的实现
- 自平衡二叉查找树(二)-----------红黑树(redblack tree)分析和代码实现
- 红黑树与C实现算法 - RedBlackTree.c
- 红黑树(RedBlackTree),平衡树(BalancedTree),SkipList 的实现
- 数据结构 - 红黑树(Red Black Tree)删除详解与实现(Java)
- 红黑树(red black tree) Common Lisp 实现
- [转载] 红黑树(Red Black Tree)- 对于 JDK TreeMap的实现
- 红黑树(RedBlackTree)实现
- 红黑树(Red Black Tree) - Flex实现
- 红黑树(Red Black Tree)
- [转载]红黑树(Red Black Tree)
- 红黑树(Red Black Tree)
- RedBlackTree 红黑树——接力写
- 红黑树(RedblackTree)上--增加节点
- 编程练习——红黑树(RedBlackTree)
- 红黑树(Red Black Tree)
- C#与数据结构--树论--红黑树(RED BLACK TREE)
- RedBlackTree(红黑树)--一种自平衡(最优)的二叉搜索树算法
- 红黑树—Red Black Tree