红黑树(red black tree)
来源:互联网 发布:unix高级编程第三版 编辑:程序博客网 时间:2024/05/01 13:34
红黑树是满足下列红黑条件的二叉查找树
1 根节点是黑色;
2 叶节点是黑色;
3 从根到任意叶节点有相同数量的黑节点(有相同的黑高度);
4 红节点的子节点只能是黑节点;
5 节点要么是红色,要么是黑色;
二叉查找树是一种二叉树,它至多有两个子树。其中左子树所有节点的值
小于它的值,右子树所有节点的值大于它的值。
红黑树是一种平衡树,但没有AVL树那么极端,因此它的插入和删除效率高于AVL树。
红黑树允许左子树和右子树的高度至多相差2,AVL树至多相差1,这就显著
减少了红黑树插入和删除时对节点的旋转次数。红黑树插入和删除时的旋转次数
至多2次。
下面的代码是一个简化的测试版本。
我测试过它在处理一百七十多万节点时效率,与STL的set基本持平,修改内存分配策略
(该版本是个简化版,并未包含内存分配的部分,只是简单的使用new和delete)
后效率略高于STL set,这是因为STL set功能很多,考虑的问题也很多,而我的简单。
该代码为了处理简单,把null作为叶节点,颜色为黑。
编译:
g++ -g -O2 -W -Wall -Wextra -o mytest main.cpp rbtree.h
执行:
./mytest
参考文献:
《算法导论》
=====================================================================
main.cpp:
// modify 2010年 10月 12日 星期二 09:09:52 CST
// author: 李小丹(Li Shao Dan) 字 殊恒(shuheng)
// K.I.S.S
// S.P.O.T
// using to test rb_tree
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "rbtree.h"
using namespace std;
#define MAX_NUMBER 30
#define MAX_VALUE 800
static int print_n = 0;
int print_node(const int &d)
{
cout << d << '/t';
if(!(++print_n % 10))
cout << endl;
return 0;
}
int main()
{
srand(time(0));
rb_tree<int> rbt;
for(int i = 0; i < MAX_NUMBER; ++i)
rbt.insert(rand() % MAX_VALUE);
print_n = 0;
if(rbt.travers(rb_tree<int>::BACK, print_node))
cerr << "error!!/n";
cout << endl;
print_n = 0;
if(rbt.travers(rb_tree<int>::FRONT, print_node))
cerr << "error!/n";
cout << endl;
print_n = 0;
if(rbt.travers(rb_tree<int>::MIDDLE, print_node))
cerr << "error!/n";
cout << endl;
cout << "size=" << rbt.size() << endl;
int data;
cout << "Search:/n";
cout << "Please input a number to search./n";
while(cin >> data) {
if(rbt.search(data))
cout << "Success!/n";
cout << "Please input a number to search./n";
}
cin.clear();
cout << "Remove:/n";
cout << "Please input a number to remove./n";
while(cin >> data) {
if(!rbt.remove(data)) {
cerr << "success!/n";
}
cout << "Please input a number to remove./n";
}
print_n = 0;
if(rbt.travers(rb_tree<int>::MIDDLE, print_node))
cerr << "error!/n";
cout << endl;
if(!rbt.max(&data))
cout << "max: " << data << endl;
if(!rbt.min(&data))
cout << "min: " << data << endl;
cout << "successor:/n";
cin.clear();
cout << "Please input a number to search successor./n";
while(cin >> data) {
if(rbt.successor(data, &data))
cerr << "error!/n";
cout << data << endl;
cout << "Please input a number to search successor./n";
}
cout << "predecessor:/n";
cout << "Please input a number to search predecessor./n";
cin.clear();
while(cin >> data) {
if(rbt.predecessor(data, &data))
cerr << "error!/n";
cout << data << endl;
cout << "Please input a number to search predecessor./n";
}
rbt.clear();
return 0;
}
=====================================================================
rbtree.h:
// modify 2009年 09月 09日 星期三 10:09:31 CST
// author: 李小丹(Li Shao Dan) 字 殊恒(shuheng)
// K.I.S.S
// S.P.O.T
// red black tree
/*
*
* Copyright © 2009 李小丹(Li Shao Dan)
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. 李小丹(Li Shao Dan) makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*/
#ifndef RBTREE_H
#define RBTREE_H
template <class T>
class rb_tree {
public:
typedef int (*travers_fun_t)(const T &);
enum ORDER {FRONT, MIDDLE, BACK};
rb_tree();
~rb_tree();
bool search(const T &);
int insert(const T &);
int remove(const T &);
void clear();
size_t size() { return count; }
int travers(int, travers_fun_t);
int max(T *);
int min(T *);
int successor(const T &, T *);
int predecessor(const T &, T *);
private:
template <class N>
struct node;
node<T> *search_core(const T &);
void ins_balance(node<T> *);
void rm_balance(node<T> *);
void left_rotate(node<T> *);
void right_rotate(node<T> *);
inline int what_color(node<T> *);
node<T> *next_node(node<T> *);
node<T> *prev_node(node<T> *);
int front_travers(travers_fun_t, node<T> *);
int mid_travers(travers_fun_t, node<T> *);
int back_travers(travers_fun_t, node<T> *);
node<T> *minmum(node<T> *);
node<T> *maxmum(node<T> *);
node<T> *core_successor(node<T> *);
node<T> *core_predecessor(node<T> *);
private:
enum COLOR {RED, BLACK};
template <class N>
struct node {
node(const N &d)
:data(d), color(RED), parent(0), left(0), right(0)
{}
~node()
{
if(left) delete left;
if(right) delete right;
}
N data;
int color;
node *parent;
node *left;
node *right;
};
node<T> *root;
size_t count;
};
template <class T>
rb_tree<T>::rb_tree()
:root(0), count(0)
{
}
template <class T>
rb_tree<T>::~rb_tree()
{
if(root) delete root;
}
template <class T>
void rb_tree<T>::clear()
{
if(root) delete root;
root = 0;
count = 0;
}
template <class T>
int rb_tree<T>::front_travers(travers_fun_t fun, node<T> *p)
{
if(p) {
int ret;
if((ret = fun(p->data)))
return ret;
if((ret = front_travers(fun, p->left)))
return ret;
if((ret = front_travers(fun, p->right)))
return ret;
}
return 0;
}
template <class T>
int rb_tree<T>::mid_travers(travers_fun_t fun, node<T> *p)
{
if(p) {
int ret;
if((ret = mid_travers(fun, p->left)))
return ret;
if((ret = fun(p->data)))
return ret;
if((ret = mid_travers(fun, p->right)))
return ret;
}
return 0;
}
template <class T>
int rb_tree<T>::back_travers(travers_fun_t fun, node<T> *p)
{
if(p) {
int ret;
if((ret = back_travers(fun, p->left)))
return ret;
if((ret = back_travers(fun, p->right)))
return ret;
if((ret = fun(p->data)))
return ret;
}
return 0;
}
template <class T>
int rb_tree<T>::travers(int o, travers_fun_t fun)
{
switch(o) {
case FRONT:
return front_travers(fun, root);
break;
case MIDDLE:
return mid_travers(fun, root);
break;
case BACK:
return back_travers(fun, root);
break;
default:
return -1;
}
return 0;
}
template <class T>
int rb_tree<T>::max(T *d)
{
node<T> *p;
if(root && (p = maxmum(root))) {
*d = p->data;
return 0;
}
return -1;
}
template <class T>
int rb_tree<T>::min(T *d)
{
node<T> *p;
if(root && (p = minmum(root))) {
*d = p->data;
return 0;
}
return -1;
}
template <class T>
int rb_tree<T>::successor(const T &in, T *out)
{
node<T> *p;
if((p = search_core(in)) &&
(p = core_successor(p))) {
*out = p->data;
return 0;
}
return -1;
}
template <class T>
int rb_tree<T>::predecessor(const T &in, T *out)
{
node<T> *p;
if((p = search_core(in)) &&
(p = core_predecessor(p))) {
*out = p->data;
return 0;
}
return -1;
}
template <class T>
rb_tree<T>::node<T> *rb_tree<T>::minmum(node<T> *p)
{
for(; p->left; p = p->left) ;
return p;
}
template <class T>
rb_tree<T>::node<T> *rb_tree<T>::maxmum(node<T> *p)
{
for(; p->right; p = p->right) ;
return p;
}
template <class T>
rb_tree<T>::node<T> *rb_tree<T>::core_successor(node<T> *p)
{
if(p->right)
return minmum(p->right);
while(p->parent && p == p->parent->right)
p = p->parent;
return p->parent;
}
template <class T>
rb_tree<T>::node<T> *rb_tree<T>::core_predecessor(node<T> *p)
{
if(p->left)
return maxmum(p->left);
while(p->parent && p == p->parent->left)
p = p->parent;
return p->parent;
}
template <class T>
int rb_tree<T>::insert(const T &d)
{
node<T> **p = &root, *par = root;
while(*p) {
par = *p;
if((*p)->data > d)
p = &((*p)->left);
else if((*p)->data < d)
p = &((*p)->right);
else
return -1;
}
*p = new node<T>(d);
if(*p) {
(*p)->parent = par;
ins_balance(*p);
root->color = BLACK;
++count;
return 0;
}
return -1;
}
template <class T>
bool rb_tree<T>::search(const T &d)
{
node<T> *p;
if((p = search_core(d))) {
return true;
}
return false;
}
template <class T>
rb_tree<T>::node<T> *rb_tree<T>::search_core(const T &d)
{
node<T> *p = root;
while(p) {
if(p->data > d)
p = p->left;
else if(p->data < d)
p = p->right;
else
return p;
}
return 0;
}
template <class T>
int rb_tree<T>::remove(const T &d)
{
node<T> *p = root;
while(p && p->data != d) {
if(p->data > d) p = p->left;
else p = p->right;
}
if(p) {
node<T> *tmp;
if((tmp = next_node(p))) {
p->data = tmp->data;
p = tmp;
} else if((tmp = prev_node(p))) {
p->data = tmp->data;
p = tmp;
}
if(p->left) tmp = p->left;
else tmp = p->right;
if(p->parent) {
if(p == p->parent->left)
p->parent->left = tmp;
else
p->parent->right = tmp;
if(tmp) tmp->parent = p->parent;
} else {
root = tmp;
}
if(p->color == BLACK && tmp)
rm_balance(tmp);
p->left = p->right = 0;
delete p;
if(root) root->color = BLACK;
--count;
return 0;
}
return -1;
}
template <class T>
inline int rb_tree<T>::what_color(node<T> *p)
{
if(p) return p->color;
return BLACK;
}
template <class T>
rb_tree<T>::node<T> *rb_tree<T>::next_node(node<T> *p)
{
if((p = p->right))
for(; p->left; p = p->left) ;
return p;
}
template <class T>
rb_tree<T>::node<T> *rb_tree<T>::prev_node(node<T> *p)
{
if((p = p->left))
for(; p->right; p = p->right) ;
return p;
}
template <class T>
void rb_tree<T>::left_rotate(node<T> *p)
{
node<T> *tmp = p->left;
p->left = p->parent;
p->parent = p->left->parent;
p->left->parent = p;
p->left->right = tmp;
if(p->parent) {
if(p->parent->left == p->left)
p->parent->left = p;
else
p->parent->right = p;
}
if(tmp) tmp->parent = p->left;
if(p->left == root)
root = p;
}
template <class T>
void rb_tree<T>::right_rotate(node<T> *p)
{
node<T> *tmp = p->right;
p->right = p->parent;
p->parent = p->right->parent;
p->right->parent = p;
p->right->left = tmp;
if(p->parent) {
if(p->parent->left == p->right)
p->parent->left = p;
else
p->parent->right = p;
}
if(tmp) tmp->parent = p->right;
if(p->right == root)
root = p;
}
template <class T>
void rb_tree<T>::ins_balance(node<T> *p)
{
node<T> *pnt = p->parent;
node<T> *uncle;
while(what_color(pnt) == RED) {
if(pnt == pnt->parent->left) {
uncle = pnt->parent->right;
if(what_color(uncle) == RED) {
uncle->color = BLACK;
pnt->color = BLACK;
pnt->parent->color = RED;
p = pnt->parent;
pnt = p->parent;
} else {
if(p == pnt->right) {
left_rotate(p);
//p->left->color = BLACK;
//p->color = RED;
p = p->left;
pnt = p->parent;
}
//p->color = BLACK;
pnt->color = BLACK;
pnt->parent->color = RED;
//p = pnt;
right_rotate(pnt);
//pnt = p->parent;
}
} else /*if(pnt == pnt->parent->right)*/ {
uncle = pnt->parent->left;
if(what_color(uncle) == RED) {
uncle->color = BLACK;
pnt->color = BLACK;
pnt->parent->color = RED;
p = pnt->parent;
pnt = p->parent;
} else {
if(p == pnt->left) {
right_rotate(p);
//p->right->color = BLACK;
//p->color = RED;
p = p->right;
pnt = p->parent;
}
//p->color = BLACK;
pnt->color = BLACK;
pnt->parent->color = RED;
//p = pnt;
left_rotate(pnt);
//pnt = p->parent;
}
}
}
}
template <class T>
void rb_tree<T>::rm_balance(node<T> *p)
{
node<T> *pnt, *bro;
while(p != root && p->color == BLACK) {
pnt = p->parent;
if(p == pnt->left) {
if(what_color(pnt->right) == RED) {
pnt->color = RED;
pnt->right->color = BLACK;
left_rotate(pnt->right);
}
bro = pnt->right;
if(!bro || (what_color(bro->left) == BLACK &&
what_color(bro->right) == BLACK)) {
if(bro) bro->color = RED;
p = pnt;
} else {
if(!bro->right || bro->right->color == BLACK) {
bro->color = RED;
bro->left->color = BLACK; //
right_rotate(bro->left);
bro = pnt->right;
}
bro->color = pnt->color;
pnt->color = BLACK;
bro->right->color = BLACK;
left_rotate(bro);
p = root;
}
} else {
if(what_color(pnt->left) == RED) {
pnt->color = RED;
pnt->left->color = BLACK;
right_rotate(pnt->left);
}
bro = pnt->left;
if(!bro || (what_color(bro->right) == BLACK &&
what_color(bro->left) == BLACK)) {
if(bro) bro->color = RED;
p = pnt;
} else {
if(!bro->left || bro->left->color == BLACK) {
bro->color = RED;
bro->right->color = BLACK; //
left_rotate(bro->right);
bro = pnt->left;
}
bro->color = pnt->color;
pnt->color = BLACK;
bro->left->color = BLACK;
right_rotate(bro);
p = root;
}
}
}
p->color = BLACK;
}
#endif
感谢阅读!
- 红黑树Red-Black-Tree
- 红黑树(Red Black Tree)
- 红黑树(red black tree)
- Red-Black Tree红黑树
- Red-Black Tree 红黑树
- 红黑树red-black-tree
- 红黑树(Red-Black Tree)
- 红黑树(Red Black Tree)
- 红黑树(Red Black Tree)
- 红黑树(Red Black Tree)
- 红黑树(red-black tree)
- 红黑树(Red Black Tree)
- 红黑树(Red Black Tree)
- 红黑树(Red Black Tree)
- 红黑树(Red Black Tree)
- 红黑树 RBT (Red Black Tree)
- 红黑树(Red Black Tree)
- 红黑树(Red Black Tree)
- use this as the default and do not ask again
- 推荐几款Jquery插件,工作适用
- Java获取路径
- 列举 CString转char 的四种方法
- 开始程序员之旅
- 红黑树(red black tree)
- 存储信息和输出信息
- 总结Javascript的几种页面刷新的方法!
- (zt)MySQL中的定时执行
- VS2005 安装 WTL80
- 算法导论排序算法之堆排序(五)
- 公钥和私钥
- linux Pam密码安全管理
- c#winform 避免打开多个相同窗口!