您的位置:首页 > 其它

高效的平衡搜索树——红黑树

2016-07-24 23:53 399 查看
红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:

性质1. 节点是红色或黑色。

性质2. 根节点是黑色。

性质3 每个叶节点是黑色的。

性质4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)

红黑树的插入分为以下三种情况

第一种情况:

cur为红节点,parent为红节点,grandfather为黑节点,uncle存在且为红
变换:将parent改为黑节点,grandfather改为红节点,然后把grandfather当成cur,并且向上调整



第二种情况:

cur为红节点,parent为红节点,grandfather为黑节点,uncle不存在/uncle为红节点
变换:(1)parent为grandfather的左孩子,cur为parent的左孩子,则进行右单旋转
(2)parent为grandfather的右孩子,cur为parent的右孩子,则进行左单旋转
最后,将parent变为黑节点,将grandfather变为红节点



第三种情况:

cur为红节点,parent为红节点,grandfather为黑节点,uncle不存在/uncle为黑节点
变换:(1)parent为grandfather的左孩子,cur为parent的右孩子,则针对parent进行左单旋转
(2)parent为grandfather的右孩子,cur为parent的左孩子,则针对parent进行右单旋转
此时情况变成了情况2,可以按照情况2的办法来处理



变色后出现的情况讨论



关于红黑树中用到的旋转图解





下面是代码分析:

"RBTree.h"

#pragma once

enum Colour
{
RED,
BLACK,
};

template<class K,class V>
class RBTreeNode
{
public:
RBTreeNode(const K& key,const V& value)
:_left(NULL)
,_right(NULL)
,_parent(NULL)
,_key(key)
,_value(value)
,_col(RED)
{}
public:
//定义一个三叉链
RBTreeNode<K,V>* _left;//左孩子
RBTreeNode<K,V>* _right;//右孩子
RBTreeNode<K,V>* _parent;//父亲

K _key;
V _value;
Colour _col;
};

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* cur = _root;
Node* parent = NULL;
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->_left = cur;
cur->_parent = parent;
}
else//parent->_key < key
{
parent->_right = cur;
cur->_parent = parent;
}

while ((cur != _root) && (parent->_col == RED))//保证了grandfher的存在
{
Node* grandfather = parent->_parent;
if (grandfather->_left == parent)
{
Node* uncle = grandfather->_right;
//情况1  见下图
if ((uncle) && (uncle->_col == RED))
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
//情况3  见下图
if (cur == parent->_right)
{
_RotateL(parent);
swap(parent,cur);
}
//情况2   见下图
parent->_col = BLACK;
grandfather->_col = RED;
_RotateR(grandfather);

break;
}
}
else //grandfather->_right == parent
{
Node* uncle = parent->_left;
//情况1  见下图
if ((uncle) && (uncle->_col == RED))
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
//情况3  见下图
if (parent->_left == cur)
{
_RotateR(parent);
swap(parent,cur);
}
//情况3
parent->_col = BLACK;
grandfather->_col = RED;
_RotateL(grandfather);

break;
}
}
_root->_col = BLACK;//记得每次调整完成后,整课二叉树的根节点的颜色要调成黑色
//此时才满足二叉树的性质
}
}
void InOrder()
{
_InOrder(_root);
cout<<endl;
}
bool IsBlance()
{
//满足一棵红黑树的性质
//1.根节点是黑色的
//2.没有连续的红节点
//3、每条路径上的黑色节点数目相同
//4、最长路径不超过最短路径的两倍

if (_root == NULL)
{
//空数也满足红黑树的性质
return true;
}
if (_root->_col == RED)
{
//违背了性质的第一条
return false;
}

int k = 0;
Node* cur = _root;
while (cur)
{
if (cur->_col == BLACK)
{
k++;
}
//求出任意一条路径的黑色节点数量
cur = cur->_left;
}
int count = 0;

return _IsBlance(_root,k,count);
}
private:
bool _IsBlance(Node* root,const int k,int count)
{
if (root == NULL)
{
//空树满足红黑树的性质
return true;
}
return _IsBlance(root->_left,k,count)
&& _IsBlance(root->_right,k,count);

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)
&& (k != count))
{
cout<<root->_key<<"  路径上的黑色节点数目不相同"<<endl;
return false;
}
}
void _RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
Node* ppNode = parent->_parent;

parent->_right = subRL;
if (subRL)
{
subRL->_parent = parent;
}
subR->_left = parent;
parent->_parent = subR;

if (ppNode == NULL)
{
_root = subR;
subR->_parent = NULL;
}
else  //ppNode != NULL
{
if (ppNode->_left == parent)
{
ppNode->_left = subR;
}
else  //ppNode->_right == parent
{
ppNode->_right = subR;
}

subR->_parent = ppNode;
}
}
void _RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
Node* ppNode = parent->_parent;

parent->_left = subLR;
if (subLR)
{
subLR->_parent = parent;
}
subL->_right = parent;
parent->_parent = subL;

if (ppNode == NULL)
{
_root = subL;
subL->_parent = NULL;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subL;
}
else //ppNode->_right == parent
{
ppNode->_right = subL;
}

subL->_parent = ppNode;
}
}
void _InOrder(Node* root)
{
if (root == NULL)
{
return;
}

_InOrder(root->_left);
cout<<root->_key<<" ";
_InOrder(root->_right);
}
private:
Node* _root;
};


"test.cpp"

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
#include "RBTree.h"

void Test()
{
RBTree<int,int> rbt;
//int arr[] = {16,3,7,11,9,26,18,14,15};
int arr[] = {48,12,56,32,99,11,10,78,22};
int size = sizeof(arr)/sizeof(arr[0]);

for (int i = 0;i < size;i++)
{
rbt.Insert(arr[i],i);
cout<<"IsBlance? "<<rbt.IsBlance()<<endl;
}
rbt.InOrder();
cout<<"IsBlance? "<<rbt.IsBlance()<<endl;
}

int main()
{
Test();
system("pause");
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: