說說紅黑樹

紅黑樹的性質:
        紅黑樹的每一個節點(node)都有一個flag位,不是紅色(Red)就是黑色(Black)。經過對任意一條從跟節點到葉子節點的簡單路徑的顏色加以約束,能夠保證沒有
一條路徑會比其它路徑長出2倍,這樣便使得紅黑樹能夠達到近似平衡的。
        每一個node包含5個屬性和所屬數據,固然有些優化了的紅黑樹可能更爲複雜,這裏不討論。
            typedef struct Node{
                struct Node* left;  //指向左子節點
                struct Node* right; //指向右子節點
                enum Color color;   //節點顏色
                int key;            //關鍵字
                struct Node* p;     //節點的父節點
                struct Data* data;  //節點數據,前5個爲屬性
            } *rb_node_ptr,rb_node;
        一顆紅黑樹一定知足如下5個性質:
            1.每一個節點是黑色或紅色;
            2.跟節點是黑色;
            3.紅色節點的子節點一定爲黑色;
            4.葉子節點爲黑色;
            5.從一個節點出發(不包含該節點)到葉子節點的任意簡單路徑所通過的黑色節點數目一定一致。
        一般使用哨兵來處理紅黑樹的邊界條件。所謂紅黑樹的哨兵,就是增長一個節點來收集全部指向葉子節點的普通節點的指向,這樣不會影響紅黑樹的性質,並且能夠節省空間。因爲節點到葉子節點的任意簡單路徑所通過的黑節點數目是明肯定義的,所以定義爲從跟節點到葉子節點的所通過的黑節點數目,稱爲「黑高(black-height)。node

 

紅黑樹數型改變時性質的維護:
        隨着紅黑樹的樹形變化,好比在add,delete等操做後,會改變當前樹形。爲維持紅黑樹的性質必需對數據節點進行調整。ios

節點的旋轉:
        維持紅黑樹的性質的方法是對節點進行旋轉,旋轉包括左旋和右旋。旋轉操做並不會改變關鍵字的先後順序。我的理解這個左旋和右旋其實理解爲順時針旋轉和逆時針旋轉更形象。旋轉涉及到兩個節點x,y和三個子樹alpha,gama,beta,如圖所示。優化

添加數據:this

C++代碼清單:指針

redblacktree.hcode

#ifndef _REDBLACKTREE_NODE_
#define _REDBLACKTREE_NODE_
#include<iostream>
enum Color
{
    RED,
    BLACK
};

struct data
{
  int d;
};
typedef struct RedBlackTreeNode
{
    struct data use_data;
    int key;
    struct RedBlackTreeNode* lchild;
    struct RedBlackTreeNode* rchild;
    struct RedBlackTreeNode* parent;
    enum Color color;
}red_black_tree_node,*red_black_tree_node_ptr;

class RedBlackTree
{
private:
    red_black_tree_node_ptr root;
    red_black_tree_node     guard;
public:
    RedBlackTree();
    ~RedBlackTree();
private:
    void init_tree();
    void destroy_tree();
    void red_black_tree_fixup(red_black_tree_node_ptr);
public:
    void insert_node(red_black_tree_node&);
private:
    red_black_tree_node_ptr get_node_ptr(red_black_tree_node&);
    void left_rotate(red_black_tree_node_ptr&);
    void right_rotate(red_black_tree_node_ptr&);
};
#endif //redblacktree.h

redblacktree.cc get

#include "redblacktree.h"
#include <cstdio>
#include <iostream>

RedBlackTree::RedBlackTree()
{
  init_tree();
}

RedBlackTree::~RedBlackTree()
{
    destroy_tree();
}

void RedBlackTree::init_tree()
{
    this->guard.color = BLACK;
    this->guard.lchild = NULL;
    this->guard.rchild = NULL;
    this->guard.parent = NULL;
    this->guard.key = 0;
    this->root = get_node_ptr(this->guard);
}

void RedBlackTree::destroy_tree()
{

}

red_black_tree_node_ptr RedBlackTree::get_node_ptr(red_black_tree_node& node)
{
    return &node;
}

void RedBlackTree::insert_node(red_black_tree_node& node)
{
    red_black_tree_node_ptr y_ptr = get_node_ptr(this->guard);
    red_black_tree_node_ptr x_ptr = this->root;
    while(x_ptr != get_node_ptr(this->guard)){
	y_ptr = x_ptr;
	if(node.key <= x_ptr->key)
	    x_ptr = x_ptr->lchild;
	else 
	    x_ptr = x_ptr->rchild;
    }
    node.parent = y_ptr;
    
    if(y_ptr == get_node_ptr(this->guard)){
	this->root = get_node_ptr(node);
    }
    else if(node.key <= y_ptr->key){
	y_ptr->lchild = get_node_ptr(node);	
    }
    else{
	y_ptr->rchild = get_node_ptr(node);
    }
node.lchild = get_node_ptr(this->guard);
node.rchild = get_node_ptr(this->guard);
node.color = RED;

red_black_tree_fixup(get_node_ptr(node));
}

void RedBlackTree::red_black_tree_fixup(red_black_tree_node_ptr node_ptr)
{
    while(node_ptr->parent->color == RED){
	if(node_ptr->parent == node_ptr->parent->parent->lchild){
	    red_black_tree_node_ptr uncle_ptr = node_ptr->parent->parent->rchild;
	    if(uncle_ptr->color == RED){
		node_ptr->parent->color = BLACK;
		uncle_ptr->color = BLACK;
		node_ptr->parent->parent->color = RED;
		
		node_ptr = node_ptr->parent->parent;
	    }
	    else if(node_ptr == node_ptr->parent->rchild){
		node_ptr = node_ptr->parent;
		left_rotate(node_ptr);
	    }
	    node_ptr->parent->color = BLACK;
	    node_ptr->parent->parent->color = RED;
	    right_rotate(node_ptr->parent->parent);
	}
	else if(node_ptr->parent == node_ptr->parent->parent->rchild){
	    red_black_tree_node_ptr uncle_ptr = node_ptr->parent->parent->lchild;
	    if(uncle_ptr->color == RED){
		node_ptr->parent->color = BLACK;
		uncle_ptr->color = BLACK;
		node_ptr->parent->parent->color = RED;
		node_ptr = node_ptr->parent->parent;
	    }
	    else if(node_ptr == node_ptr->parent->lchild){
		node_ptr = node_ptr->parent;
		right_rotate(node_ptr);
	    }
	    node_ptr->parent->color = BLACK;
	    node_ptr->parent->parent->color = RED;
	    left_rotate(node_ptr->parent->parent);
	}
    }

this->root->color = BLACK;
}

void RedBlackTree::left_rotate(red_black_tree_node_ptr& node_ptr)
{
    red_black_tree_node_ptr right_sub_node_ptr = node_ptr->rchild;
    node_ptr->rchild = right_sub_node_ptr->lchild;
    if(right_sub_node_ptr->lchild != get_node_ptr(this->guard)){
	right_sub_node_ptr->lchild->parent = node_ptr;
    }
    right_sub_node_ptr->parent = node_ptr->parent;

    if(node_ptr->parent == get_node_ptr(this->guard)){
	this->root = right_sub_node_ptr;
    }
    else if(node_ptr == node_ptr->parent->lchild){
	node_ptr->parent->lchild = right_sub_node_ptr;
    }
    else{
	node_ptr->parent->rchild = right_sub_node_ptr;
    }
    
    right_sub_node_ptr->lchild = node_ptr;
    node_ptr->parent = right_sub_node_ptr;
}

void RedBlackTree::right_rotate(red_black_tree_node_ptr& node_ptr)
{
    red_black_tree_node_ptr left_sub_node_ptr = node_ptr->lchild;
    node_ptr->lchild = left_sub_node_ptr->rchild;
    if(left_sub_node_ptr->rchild != get_node_ptr(this->guard)){
	left_sub_node_ptr->rchild->parent = node_ptr;
    }
    left_sub_node_ptr->parent = node_ptr->parent;
    
    if(node_ptr->parent == get_node_ptr(this->guard)){
	this->root = left_sub_node_ptr;
    }
    else if(node_ptr == node_ptr->parent->rchild){
	node_ptr->parent->rchild = left_sub_node_ptr;
    }
    else{
	node_ptr->parent->lchild = left_sub_node_ptr;
    }

    left_sub_node_ptr->rchild = node_ptr;
    node_ptr->parent = left_sub_node_ptr;
}

main.ccit

#include "redblacktree.h"

int main()
{
  RedBlackTree tree;
  red_black_tree_node node1;
  node1.key = 11;
  tree.insert_node(node1);  
  red_black_tree_node node2;
  node2.key = 12;
  tree.insert_node(node2);  
return 0;
}

 

搞清楚節點和節點指針的關係:
io

相關文章
相關標籤/搜索