紅黑樹

紅黑樹是一棵二叉搜索樹,它在每個節點上增加了一個存儲位來表示節點的顏色,可以是Red或Black。通過對任何一條從根到葉子簡單路徑上的顏色來約束,紅黑樹保證最長路徑不超過最短路徑的兩倍,因而近似於平衡。

  • 紅黑樹是滿足下面紅黑性質的二叉搜索樹

  1. 每個節點,不是紅色就是黑色的

  2. 根節點是黑色的

  3. 如果一個節點是紅色的,則它的兩個子節點是黑色的(沒有連續的紅節點)

  4. 對每個節點,從該節點到其所有後代葉節點的簡單路徑上,均包含相同數目的黑色節點。(每條路徑的黑色節點的數量相等

  5. 每個葉子節點都是黑色的(這裏的葉子節點是指的NIL節點(空節點))

  • 插入的幾種情況

ps:cur爲當前節點,p爲父節點,g爲祖父節點,u爲叔叔節點

1.第一種情況

cur爲紅,p爲紅,g爲黑,u存在且爲紅

則將p,u改爲黑,g改爲紅,然後把g當成cur,繼續向上調整。

wKiom1ePLb_xL9UfAABBkJGL6H8416.png-wh_50

2.第二種情況

cur爲紅,p爲紅,g爲黑,u不存在/u爲黑

p爲g的左孩子,cur爲p的左孩子,則進行右單旋轉;相反,p爲g的右孩子,cur爲p的右孩子,則進行左單旋轉

p、g變色--p變黑,g變紅

wKiom1ePLgLx-K7DAABA_WHqSaQ601.png-wh_50

3.第三種情況

cur爲紅,p爲紅,g爲黑,u不存在/u爲黑

p爲g的左孩子,cur爲p的右孩子,則針對p做左單旋轉;相反,p爲g的右孩子,cur爲p的左孩子,則針對p做右單旋轉

則轉換成了情況2

wKioL1ePLkmQOAM7AAA9lWvBKi4857.png-wh_50

#pragma once

#include<iostream>

using namespace std;


enum Colour

{

RED,

BLACK,

};

template<class K,class V>

struct RBTreeNode

{

RBTreeNode<K, V>* _left;

RBTreeNode<K, V>* _right;

RBTreeNode<K, V>* _parent;

K _key;

V _value;

Colour _col;

RBTreeNode(const K& key, const V& value)

:_key(key)

, _value(value)

, _left(NULL)

, _right(NULL)

, _parent(NULL)

, _col(RED)

{}

};

template<class K, class V>

class RBTree

{

typedef RBTreeNode<K, V> Node;

public:

RBTree()

:_root(NULL)

{}

bool Insert(const K& key, const V& value)

{

if (_root == NULL)

{

_root = new Node(key, value);

_root->_col = BLACK;

return true;

}

Node* parent = NULL;

Node* cur = _root;

while (cur)

{

if (cur->_key > key)

{

parent = cur;

cur = cur->_left;

}

else if (cur->_key < key)

{

parent = cur;

cur = cur->_right;

}

else

{

return false;

}

}

cur = new Node(key, value);

if (parent->_key < key)

{

parent->_right = cur;

cur->_parent = parent;

}

else

{

parent->_left = cur;

cur->_parent = parent;

}

while (cur != _root && parent->_col == RED)//grandfather肯定不爲空,根節點的顏色爲黑色

{

Node* grandfather = parent->_parent;

if (grandfather->_left == parent)//parent爲的grandfather左孩子

{

Node* uncle = grandfather->_right;

if (uncle && uncle->_col == RED)//uncle存在並且爲紅色的

{

parent->_col = uncle->_col = BLACK;

grandfather->_col = RED;

cur = grandfather;

parent = cur->_parent;

}

else

{

if (cur = parent->_right)//cur爲parent的右孩子,先把它左單旋爲左孩子

{

RotateL(parent);

swap(parent, cur);

}

parent->_col = BLACK;

grandfather->_col = RED;

RotateR(grandfather);

break;

}

}

else

{

Node* uncle = grandfather->_left;

if (uncle && uncle->_col == RED)

{

parent->_col = uncle->_col = BLACK;

grandfather->_col = RED;

cur = grandfather;

parent = cur->_parent;

}

else

{

if (parent->_left == cur)

{

RotateR(parent);

swap(parent, cur);

}

parent->_col = BLACK;

grandfather->_col = RED;

RotateL(grandfather);

break;

}

}

}

_root->_col = BLACK;

}

void Inorder()

{

_Inorder(_root);

cout << endl;

}

bool IsBalance()

{

if (_root == NULL)

{

return true;

}

if (_root->_col == RED)//根節點必須是黑色的

{

return false;

}

Node* cur = _root;

int k = 0;

while (cur)

{

if (cur->_col == BLACK)

{

k++;

}

cur = cur->_left;

}

int count = 0;

return _IsBalance(_root, k, count);

}

Node* Find(const K& key)

{

if (_root == NULL)

{

return NULL;

}

Node* cur = _root;

while (cur)

{

if (cur->_key > key)

{

cur = cur->_left;

}

else if (cur->_key < key)

{

cur = cur->_right;

}

else

{

return cur;

}

}

return NULL;

}

protected:

bool _IsBalance(Node* root, const int k, int count)

{

if (root == NULL)

{

return true;

}

if (root->_col == RED && root->_parent->_col == RED)

{

cout << "出現連續的紅色節點" << root->_key << endl;

return false;

}

if (root->_col == BLACK)

{

++count;

}

if (root->_left == NULL && root->_right == NULL && count != k)

{

cout << "黑色節點個數不相等" << root->_key << endl;

return false;

}

return _IsBalance(root->_left, k, count) && _IsBalance(root->_right, k, count);

}

void _Inorder(Node* root)

{

if (root == NULL)

{

return;

}

_Inorder(root->_left);

cout << root->_key << " ";

_Inorder(root->_right);

}

void RotateL(Node* parent)

{

Node* subR = parent->_right;

Node* subRL = subR->_left;

parent->_right = subRL;

if (subRL)

{

subRL->_parent = parent;

}

Node* ppNode = parent->_parent;

subR->_left = parent;

parent->_parent = subR;

if (ppNode == NULL)

{

_root = subR;

}

else

{

if (ppNode->_left == parent)

{

ppNode->_left = subR;

}

else

{

ppNode->_right = subR;

}

}

subR->_parent = ppNode;

}

void RotateR(Node* parent)

{

Node* subL = parent->_left;

Node* subLR = subL->_right;

parent->_left = subLR;

if (subLR)

{

subLR->_parent = parent;

}

Node* ppNode = parent->_parent;

subL->_right = parent;

parent->_parent = subL;

if (ppNode == NULL)

{

_root = subL;

}

else

{

if (ppNode->_left == parent)

{

ppNode->_left = subL;

}

else

{

ppNode->_right = subL;

}

}

subL->_parent = ppNode;

}

protected:

Node* _root;

};


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章