程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 紅黑樹的實現(int精簡版)

紅黑樹的實現(int精簡版)

編輯:C++入門知識

    最近在閱讀SGI STL源代碼,其中紅黑樹的實現比較有技術含量,但標准庫裡面是捆綁了其中的allocator, iterator(Rb_tree專用的),使用很多模板變量,實現對多種數據類型的處理。這些情況對於有較扎實C++基礎的人來說不成問題,但對於一般初學算法,而又沒有太好的C++基礎的人來說有點困難。並且SGI STL中的實現代碼寫得很精巧,節省代碼,也高效運行,但會使得功能不夠深厚的人讀起來還是比較費勁。

      這裡使用簡單的int類型節點,實現紅黑樹的創建、插入及相關內部操作的功能。目前代碼中刪除節點及其內部操作功能沒有實現。

      關於紅黑樹的五個條件(有的書上說四個,內容是等價的)以及插入節點後的調整,可以參考侯捷先生的《STL源碼剖析》,裡面有詳細的原理介紹。也可以參考《算法導論》。下面代碼可以直接使用運行,經測試正確,代碼不追求在物理運行上的效率,盡量把算法步驟表現在代碼裡,不作過多合並優化,並且已經加上不少注釋,方便閱讀。

My_Rb_Tree.h

[cpp]
#pragma once 
 
#define node_black true 
#define node_red false 
 
typedef bool node_color; 
typedef int value_type; 
 
struct node 

    node_color color; 
    node * left; 
    node * right; 
    node * parent; 
    value_type val; 
}; 
 
class My_Rb_Tree 

public: 
    My_Rb_Tree(void); 
    ~My_Rb_Tree(void); 
 
    node * InsertUnique(value_type in_val); 
    void Erase(node * in_cur); 
    node * Find(value_type _val); 
 
private: 
    node * Root(); 
    void Init(); 
    node * CreateNode(value_type _val); 
 
    void DestoryNode(node * &_n); 
 
    void RotateLeft(node * _cur); 
    void RotateRight(node * _cur); 
 
    void Rebalance(node * _cur); 
    void RebalanceForErase(node * _cur); 
 
    node * Insert(node * in_parent, node * in_cur, value_type in_value); 
 
private: 
    int node_count; 
    node * head; 
 
}; 

My_Rb_Tree.cpp

[cpp] view plaincopy
/************************************************************************/ 
/*  @brief Red-Black tree implement.
/*  @author [email protected]
/*  @date 2012.10.12
/*  @time 16:56:37                                        
/************************************************************************/ 
#include "StdAfx.h" 
#include "My_Rb_Tree.h" 
#include "assert.h" 
 
My_Rb_Tree::My_Rb_Tree(void) 
:node_count(0), 
head(0) 

    Init(); 

 
My_Rb_Tree::~My_Rb_Tree(void) 


 
node * My_Rb_Tree::Root() 

    assert(head); 
    if (!head) 
    { 
        return 0; 
    } 
    return head->parent; 

 
void My_Rb_Tree::Init() 
{    
    head = CreateNode(0); 
    if (!head) 
    { 
        return; 
    } 
    head->color = node_red; 
    head->left = head; 
    head->right = head; 
    head->parent = 0; 

 
node * My_Rb_Tree::CreateNode(value_type _val) 

    node * n = new node; 
    n->parent = 0; 
    n->left = 0; 
    n->right = 0; 
    n->color = node_red; 
    n->val = _val; 
    return n; 

 
void My_Rb_Tree::DestoryNode(node * &_n) 

    delete _n; 
    _n = 0; 

 
void My_Rb_Tree::RotateLeft(node * _cur) 

    node * _root = Root(); 
    node * r = _cur->right; 
    if (!r) 
    { 
        return; 
    } 
 
    if ( _cur ==_root ) 
    { 
        _root = r; 
        r->parent = _cur->parent; 
        _cur->parent->parent = r; 
    } 
    else 
    { 
 
    } 
    r->parent = _cur->parent; 
    if (_cur->parent->left == _cur) 
    { 
        r->parent->left = r; 
    } 
    else 
    { 
        r->parent->right = r; 
    } 
 
    _cur->right = r->left; 
    if (r->left) 
    {    
        _cur->right->parent = _cur; 
    } 
 
    r->left = _cur; 
    _cur->parent = r; 

void My_Rb_Tree::RotateRight(node * _cur) 

    node * _root = Root(); 
    node * l = _cur->left; 
    if (!l) 
    { 
        return; 
    } 
    if ( _cur == _root ) 
    { 
        _root = l; 
        l->parent = _cur->parent;//head 
        l->parent->parent = l;// head->parent 
    } 
    else 
    { 
 
        l->parent = _cur->parent; 
        if (l->parent->left == _cur) 
        { 
            l->parent->left = l; 
        } 
        else 
        { 
            l->parent->right = l; 
        } 
    } 
 
    _cur->left = l->right; 
    if (l->right) 
    { 
        _cur->left->parent = _cur; 
    } 
 
    l->right = _cur; 
    _cur->parent = l; 
 

 
void My_Rb_Tree::Rebalance(node * _cur) 

    node * _root = Root(); 
    _cur->color = node_red; 
 
    if (_cur->parent == head) // _cur is root node 
    { 
        _cur->color = node_black; 
        return; 
    } 
 
    if ( _cur->parent->color == node_black ) // now is balance state. 
    { 
        return ; 
    } 
 
    // 根據原來的樹是符合紅黑規則,祖父節點必定為黑色 
    while( (_cur != Root()) && (_cur->parent->color == node_red)) // 當前節點的父節點為紅色,違反規則 
    { 
        if (_cur->parent->parent->left == _cur->parent)  // 父節點為左子節點 
        { 
            if(_cur->parent->parent->right 
                && _cur->parent->parent->right->color == node_red)  // 伯父節點為紅 
            { 
                // 把父節點和伯父節點變成黑色,祖父節點變成紅色 
                _cur->parent->parent->right->color=node_black; 
                _cur->parent->color = node_black; 
                _cur->parent->parent->color = node_red; 
 
                // 因為祖父節點為紅色,需要繼續向上測試是否滿足規則 
                _cur = _cur->parent->parent; 
                continue; 
            } 
            else // 伯父節點為黑或不存在 
            { 
                if ( _cur == _cur->parent->right ) 
                { 
                    // 以父節點為軸,左旋轉後變成兩個左外節點連續為紅。 
                    _cur = _cur->parent; 
                    RotateLeft(_cur/*,_root*/); 
                } 
                // 改變顏色,以祖父節點為軸,右旋轉。 
                _cur->parent->parent->color = node_red; 
                _cur->parent->color = node_black; 
                RotateRight(_cur->parent->parent/*,_root*/); 
                // 此時進入下一次while判斷跳出循環 
            } 
        } 
        else // 父節點為右子節點,依照左子節點的同樣方法解決。 
        { 
            if(_cur->parent->parent->left 
                && _cur->parent->parent->left->color == node_red)  // 伯父節點為紅 
            { 
                // 把父節點和伯父節點變成黑色,祖父節點變成紅色 
                _cur->parent->parent->left->color=node_black; 
                _cur->parent->color = node_black; 
                _cur->parent->parent->color = node_red; 
 
                // 因為祖父節點為紅色,需要繼續向上測試是否滿足規則 
                _cur = _cur->parent->parent; 
                continue; 
            } 
            else // 伯父節點為黑或不存在 
            { 
                if ( _cur == _cur->parent->left ) 
                { 
                    // 以父節點為軸,右旋轉後變成兩個右外節點連續為紅。 
                    _cur = _cur->parent; 
                    RotateRight(_cur/*,_root*/); 
                } 
                // 改變顏色,以祖父節點為軸,左旋轉。 
                _cur->parent->parent->color = node_red; 
                _cur->parent->color = node_black; 
                RotateLeft(_cur->parent->parent/*,_root*/); 
                // 此時進入下一次while判斷跳出循環 
            } 
        } 
    }//end while 
    _root->color = node_black; 

 
node * My_Rb_Tree::InsertUnique(value_type in_val) 

    node * y = head; 
    node * x = Root(); 
    bool comp = true; 
    while( x )//一層一層深入找到合適的插入點 
    { 
        y = x; 
        comp = ( in_val < x->val ); 
        if (in_val == x->val) 
        { 
            return 0; 
        } 
        x = comp ? x->left : x->right; 
    } 
    return Insert(y,x,in_val); 

 
node * My_Rb_Tree::Insert(node * in_parent, node * in_cur, value_type in_value) 

    node * new_node = CreateNode(in_value); 
    if (in_parent == head) // 插入的是根節點 
    { 
        head->parent = new_node; 
        head->left = new_node; 
        head->right = new_node; 
 
        new_node->parent = head; 
        new_node->color = node_black; 
    } 
    else // 插入的是非根節點 
    { 
        if ( new_node->val < in_parent->val ) 
        { 
            in_parent->left = new_node; 
            if (in_parent == head->left) // 若插入點的父節點是最小節點,更新最小值節點指針 
            { 
                head->left = new_node; 
            } 
        } 
        else 
        { 
            in_parent->right = new_node; 
            if (in_parent == head->right)// 若插入點的父節點是最大節點,更新最大值節點指針 
            { 
                head->right = new_node; 
            } 
        } 
        new_node->parent = in_parent; 
 
        if (in_parent == head) 
        { 
            head->parent = new_node; 
            in_parent->parent = Root(); 
        } 
    } 
 
    Rebalance(new_node/*,head->parent*/); 
    node_count++; 
    return new_node; 

// 未實現,這個函數比較復雜 
void My_Rb_Tree::RebalanceForErase(node * _cur) 

    return; 

// 依賴RebalanceForErase的實現 
void My_Rb_Tree::Erase(node * in_cur) 

    return; 

 
node * My_Rb_Tree::Find(value_type _val) 

    node * _t = Root(); 
    while(_t) 
    { 
        if (_t->val == _val) 
        { 
            return _t; 
        } 
        else if (_t->val > _val) 
        { 
            _t = _t->right; 
        } 
        else 
        { 
            _t = _t->left; 
        } 
    } 
    return 0; 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved