红黑树(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

感谢阅读!