红黑树的c++代码实现,包含测试

#ifndef RB_TREE_H
#define RB_TREE_H

const int BLACK = -1;
const int RED = 1;

static int number1 = 0;   //////用于统计插入的各种情况次数的
static int number2 = 0;
static int number3 = 0;
static int number4 = 0;
static int number5 = 0;
static int number6 = 0;

struct RB_TREE_NODE{

public:
RB_TREE_NODE(int a)
{
key = a;
color = BLACK;
p =0;
left = 0;
right = 0;
}
~RB_TREE_NODE()
{
}
int key;
int color;
RB_TREE_NODE* p;
RB_TREE_NODE* left;
RB_TREE_NODE* right;

};

static RB_TREE_NODE NIL = { 0 };
#define PNIL (&NIL)

struct RB_TREE
{
RB_TREE()
{
root->left = PNIL;
root->right = PNIL;
root->p = PNIL;
}
RB_TREE_NODE* root=PNIL;

////插入节点z
void RB_TREE_INSERT(RB_TREE* root, RB_TREE_NODE* z);
///插入节点z后对该树进行调整,使之重新满足红黑树的条件
void RB_TREE_INSERT_FIXUP(RB_TREE*root, RB_TREE_NODE* z);

////删除节点z
void RB_TREE_DELETE(RB_TREE* root, RB_TREE_NODE* z);
///删除节点z后对该树进行调整,使该树重新满足红黑树的条件
void RB_TREE_DELETE_FIXUP(RB_TREE* root, RB_TREE_NODE*z);

///x的前驱,否则返回nullptr
RB_TREE_NODE* RB_TREE_PREDECESSOR(RB_TREE* root, RB_TREE_NODE* x);
///x的后驱,否则返回nullptr
RB_TREE_NODE* RB_TREE_SUCCESSOR(RB_TREE* root, RB_TREE_NODE* x);

///以x为根的树中最小值
RB_TREE_NODE* RB_TREE_MINMUM(RB_TREE_NODE* x);
///以x为根的树中的最大值
RB_TREE_NODE* RB_TREE_MAXMUM(RB_TREE_NODE* x);

///对x节点进行左旋转
void RB_LEFT_ROTATE(RB_TREE* root, RB_TREE_NODE* x);
///对x节点进行右旋转
void RB_RIGHT_ROTATE(RB_TREE*root, RB_TREE_NODE* x);

///用以节点v为根的树替换以节点u为根的树
void RB_TRANSPLANT(RB_TREE* root, RB_TREE_NODE* u, RB_TREE_NODE*v);
///搜索节点值为value的节点,并返回,搜索不到返回PNIL
RB_TREE_NODE* RB_SEARCH(RB_TREE* root, int value);
};

void RB_TREE::RB_TREE_INSERT(RB_TREE* root, RB_TREE_NODE* z)
{
z->left = PNIL; ////哨兵并非空节点,new 出的RB_TREE_NODE的左右孩子为空节点不是哨兵,所以插入前,先将左右孩子置为哨兵
z->right = PNIL;
RB_TREE_NODE* x = RB_TREE::root;
RB_TREE_NODE* y=PNIL;
while (x != PNIL)
{
y = x;
if (z->key < x->key)
x = x->left;
else
x = x->right;
}
z->p = y;
if (y == PNIL)root->root = z;
else if (z->key < y->key)y->left = z;
else y->right = z;
z->color = RED;
RB_TREE_INSERT_FIXUP(root, z);
}

void RB_TREE::RB_TREE_INSERT_FIXUP(RB_TREE* root, RB_TREE_NODE*z)
{
while (z->p->color == RED&&z->p != PNIL)
{
if (z->p->p->left == z->p)
{
RB_TREE_NODE* y = z->p->p->right;
if (y->color == RED)
{
number1++;
z->p->color = BLACK;
y->color = BLACK;
z->p->p->color = RED;
z = z->p->p;
}
else
{
number2++;
if (z == z->p->right)
{
number3++;
z = z->p;
RB_LEFT_ROTATE(root, z);
}
z->p->color = BLACK;
z->p->p->color = RED;
RB_RIGHT_ROTATE(root, z->p->p);
}
}
else
{
RB_TREE_NODE* y = z->p->p->left;
if (y->color == RED)
{
number4++;
z->p->color = BLACK;
y->color = BLACK;
z->p->p->color = RED;
z = z->p->p;
}
else
{
number5++;
if (z == z->p->left)
{
number6++;
z = z->p;
RB_RIGHT_ROTATE(root, z);
}
z->p->color = BLACK;
z->p->p->color = RED;
RB_LEFT_ROTATE(root, z->p->p);
}
}
}
root->root->color = BLACK;
}

void RB_TREE::RB_LEFT_ROTATE(RB_TREE* root, RB_TREE_NODE* x)
{
RB_TREE_NODE* y = x->right;
x->right = y->left;
if (y->left!=PNIL)
y->left->p = x;
y->p = x->p;
if (x->p == PNIL)root->root = y;
else if (x->p->left ==x)x->p->left = y;
else x->p->right = y;
x->p = y;
y->left = x;
}

void RB_TREE::RB_RIGHT_ROTATE(RB_TREE*root, RB_TREE_NODE* x)
{
RB_TREE_NODE* y = x->left;
x->left = y->right;
if (y->right != PNIL)
y->right->p = x;
y->p = x->p;
if (x->p == PNIL)root->root = y;
else if (x->p->left == x) x->p->left = y;
else x->p->right = y;
x->p = y;
y->right = x;
}

RB_TREE_NODE* RB_TREE::RB_TREE_PREDECESSOR(RB_TREE* root, RB_TREE_NODE* x)
{
if (x == RB_TREE_MINMUM(root->root))return x;
if (x->left != PNIL)return RB_TREE_MAXMUM(x->left);
RB_TREE_NODE* y = x->p;
while (y != PNIL&&x == y->left)
{
x = y;
y = y->p;
}
return y;
}

RB_TREE_NODE* RB_TREE::RB_TREE_SUCCESSOR(RB_TREE* root, RB_TREE_NODE* x)
{
if (x == RB_TREE_MAXMUM(root->root))return x;
if (x->right != PNIL)return RB_TREE_MINMUM(x->right);
RB_TREE_NODE* y = x->p;
while (y != PNIL&&x == y->right)
{
x = y;
y = y->p;
}
return y;
}

RB_TREE_NODE* RB_TREE::RB_TREE_MINMUM(RB_TREE_NODE* x)
{
while (x->left != PNIL)
x = x->left;
return x;
}

RB_TREE_NODE* RB_TREE::RB_TREE_MAXMUM(RB_TREE_NODE* x)
{
while (x->right != PNIL)
x = x->right;
return x;
}

void RB_TREE::RB_TRANSPLANT(RB_TREE* root, RB_TREE_NODE* u, RB_TREE_NODE* v)
{
if (u->p == PNIL)root->root = v;
else if (u == u->p->left)u->p->left=v;
else u->p->right = v;
if (v!=PNIL)
v->p = u->p;
}

RB_TREE_NODE* RB_TREE::RB_SEARCH(RB_TREE* root, int value)
{
RB_TREE_NODE* temp = root->root;
while (temp != PNIL&&temp->key != value)
{
if (value < temp->key)
{
temp = temp->left;
}
else
{
temp = temp->right;
}
}
return temp;
}

void RB_TREE::RB_TREE_DELETE(RB_TREE* root, RB_TREE_NODE* z)
{
RB_TREE_NODE* y = z;
RB_TREE_NODE* x;
int origin_color = y->color;

if (z->left == PNIL)
{
x = z->right;
RB_TRANSPLANT(root, z, z->right);
}
else if (z->right == PNIL)
{
x = z->left;
RB_TRANSPLANT(root, z, z->left);
}
else
{
y = RB_TREE_MINMUM(z->right);
origin_color = y->color;
x = y->right;
if (y->p == z)
{
x->p = y; ////防止y的子节点都是哨兵,进行删除调整时,需要找到x的父节点,而哨兵没有父节点。
}
else
{
RB_TRANSPLANT(root, y, y->right);
y->right = z->right;
y->right->p = y;
}
RB_TRANSPLANT(root, z, y);
y->left = z->left;
y->left->p = y;
y->color = z->color;

z->p = nullptr; ///////删除节点z时,对父节点,子节点指针置为空,只删除节点z的区域
z->right = nullptr;
z->left = nullptr;
delete z;
}
if (origin_color == BLACK)
{
RB_TREE_DELETE_FIXUP(root, x);
}
}

void RB_TREE:: RB_TREE_DELETE_FIXUP(RB_TREE* root, RB_TREE_NODE*z)
{
while (z != root->root&&z->color == BLACK)
{
if (z == z->p->left)
{
RB_TREE_NODE* y = z->p->right;
if (y->color == RED) /////case1
{
y->color = BLACK;
z->p->color = RED;
RB_LEFT_ROTATE(root, z->p);
y = z->p->right; ////转到case2,3,4中的一种
}
if (y->left->color == BLACK&&y->right->color == BLACK)
{
y->color = RED; ////case2
z = z->p;
}
else
{
if (y->right->color == BLACK)
{
y->left->color = BLACK;
y->color = RED;
RB_RIGHT_ROTATE(root, y); ////case3 转到case4
y = z->p->right;
}
y->color = z->p->color;
z->p->color = BLACK; ////case4;
y->right->color = BLACK;
RB_LEFT_ROTATE(root, z->p);
z = root->root;
}
}
else ////与以上left和right互换
{
RB_TREE_NODE* y = z->p->left;
if (y->color == RED)
{
y->color = BLACK;
z->p->color = RED;
RB_RIGHT_ROTATE(root, z->p);
y = z->p->left;
}
if (y->right->color == BLACK&&y->left->color == BLACK)
{
y->color = RED;
z = z->p;
}
else
{
if (y->left->color == BLACK)
{
y->right->color = BLACK;
y->color = RED;
RB_LEFT_ROTATE(root, y);
y = z->p->left;
}
y->color = z->p->color;
z->p->color = BLACK;
y->left->color = BLACK;
RB_RIGHT_ROTATE(root, z->p);
z = root->root;
}
}
}
z->color = BLACK;
}
#endif

#include"RB_TREE.h"
#include<iostream>
using namespace std;

void print(RB_TREE* root) /////从小到大输出所有的树节点值
{
RB_TREE_NODE* pmin = root->RB_TREE_MINMUM(root->root);
RB_TREE_NODE* pmax = root->RB_TREE_MAXMUM(root->root);
int i = 0;
while (true)
{
if (i++ % 10 == 0)cout << endl;
cout << pmin->key << " ";
if (pmin == pmax)break;
pmin = root->RB_TREE_SUCCESSOR(root, pmin);
}
}
int main()
{
int a[1000];
for (int i = 0; i < 1000; i++)
{
a[i] = rand() % 100;
}

RB_TREE* root = new RB_TREE();
for (int i = 0; i < 100; i++)
{
RB_TREE_NODE* z = new RB_TREE_NODE(a[i]);
root->RB_TREE_INSERT(root,z);
}
/////对应插入的case情况
cout << endl << number1<<" "<<number2<<" "<<number3<<" "<<number4<<" "<<number5<<" "<<number6<< endl;
cout << endl << "====================" << endl;
cout << root->root->key << " " << root->root->color << endl;

cout << root->root->left->key << " " << root->root->left->color << endl;
cout << root->root->right->key << " " << root->root->right->color << endl;

cout << root->root->left->left->key << " " << root->root->left->left->color << endl;
cout << root->root->left->right->key << " " << root->root->left->right->color << endl;

cout << root->root->right->left->key << " " << root->root->right->left->color << endl;
cout << root->root->right->right->key << " " << root->root->right->right->color << endl;

cout << "++++++++++++++++++++++++++++++++++++++" << endl;
RB_TREE_NODE* pmin = root->RB_TREE_MINMUM(root->root);
RB_TREE_NODE* pmax = root->RB_TREE_MAXMUM(root->root);
print(root);
cout << endl << endl << "++++++++++++++++++++++++++++++++" << endl;
RB_TREE_NODE* t = root->RB_SEARCH(root, 50);
if (t != PNIL)
{
cout << t->key << endl;
root->RB_TREE_DELETE(root, t);
print(root);
}
else cout << "不存在" << endl;

}

参考书目:算法导论

时间: 2024-11-10 19:55:39

红黑树的c++代码实现,包含测试的相关文章

数据结构基础(18) --红黑树的设计与实现(1)

红黑树是一种自平衡的二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组(C++ STL 中的map/set).它是在1972年由Rudolf Bayer发明的,他称之为"对称二叉B树",它现代的名字是 Leo J. Guibas 和 Robert Sedgewick 于1978年写的一篇论文中获得的.红黑树虽然很复杂,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目(来源百度

数据结构拾遗(1) --红黑树的设计与实现(上)

红黑树是一种自平衡的二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组(C++ STL 中的map/set).它是在1972年由Rudolf Bayer发明的,他称之为"对称二叉B树",它现代的名字是在 Leo J. Guibas 和 Robert Sedgewick 于1978年写的一篇论文中获得的.红黑树虽然很复杂,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目(来源:

算法05 之红-黑树

从第4节的分析中可以看出,二叉搜索树是个很好的数据结构,可以快速地找到一个给定关键字的数据项,并且可以快速地插入和删除数据项.但是二叉搜索树有个很麻烦的问题,如果树中插入的是随机数据,则执行效果很好,但如果插入的是有序或者逆序的数据,那么二叉搜索树的执行速度就变得很慢.因为当插入数值有序时,二叉树就是非平衡的了,排在一条线上,其实就变成了一个链表--它的快速查找.插入和删除指定数据项的能力就丧失了. 为了能以较快的时间O(logN)来搜索一棵树,需要保证树总是平衡的(或者至少大部分是平衡的),这

10.STL简单红黑树的实现

1.红黑树简介 二叉搜索树能够提供对数的元素插入和访问.二叉搜索树的规则是:任何节点的键值一定大于其左子树的每一个节点值,并小于右子树的每一个节点值. 常见的二叉搜索树有AVL-tree.RB-tree(红黑树).红黑树具有极佳的增.删.查性能,故我们选择红黑树作为关联式容器(associative containers)的底层结构. 红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色.在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求: 1.      节点是

算法-红黑树

之前的一片博客中关于二叉查找树在最差的情况是O(n),不能完全的达到O(lgN),在一棵还有N个节点的树中,如果树的高度为lgN,那么我们可以在lgN次比较内结束查找,不过动态插入保证树的平衡性代码量和额外的空间都会是很大的代价.为了保证查找树的平衡性,我们可以允许树中的节点可以保存多个键,标准的二叉树的节点我们可以称之为2-节点(一个键和两条链接),3-节点(含有两个键和三条链接),这就是2-3树.一个2-结点左链接小于该结点,右链接大于该节点.3-节点左链接小于所有键,中链介于两个键之间,右

红黑树 插入

红黑树是一种二叉搜索树,每个节点增加一位来储存节点的颜色,红或黑. 红黑树通过如何一条从跟到叶子的路径上各个节点的着色方式的限制,红黑树确保没有一条路径比另一条路径长两倍. 其他性质: 根节点是黑色. 红色节点的子节点都为黑色. 叶子节点或NULL空节点都为黑色.所有原来的叶子节点都有NULL的空节点作为新的叶子节点,取代了自己的叶子节点的身份,即,所有的NULL节点都是黑色的意思. 最重要一点:任何一节点到叶子节点的NULL指针的路径经过的黑色节点数相同. 插入: 左旋 以节点p为支点的话,即

算法导论 之 红黑树 - 插入[C语言]

作者:邹祁峰 邮箱:[email protected] 博客:http://blog.csdn.net/qifengzou 日期:2013.12.24 21:00 转载请注明来自"祁峰"的CSDN博客 1 引言 在之前的博文中,本人对平衡二叉树的处理做了较详尽的分析,有兴趣的朋友可以参阅博文<算法导论 之 平衡二叉树 - 创建 插入 搜索 销毁>和<算法导论 之 平衡二叉树 - 删除>.平衡二叉树AVL是严格的平衡树,在增删结点时,其旋转操作的次数较多:而红黑树

红黑树分析,看了都说好

红黑树简介 红黑树是一种自平衡的二叉查找树,是一种高效的查找树.它是由 Rudolf Bayer 于1978年发明,在当时被称为对称二叉 B 树(symmetric binary B-trees).后来,在1978年被 Leo J. Guibas 和 Robert Sedgewick 修改为如今的红黑树.红黑树具有良好的效率,它可在 O(logN) 时间内完成查找.增加.删除等操作.因此,红黑树在业界应用很广泛,比如 Java 中的 TreeMap,JDK 1.8 中的 HashMap.C++

JDK1.8 HashMap为什么在链表长度为8的时候转红黑树,为啥不能是9是10

起因: 这个问题是在面试某公司的时候面试官提的问题,当时没回答上来.归根到底还是因为自己复习基础的时候还不够仔细,也缺乏思考. 首先 我觉得需要确认一下,是不是随便什么情况下只要满足了链表长度为8就转红黑树呢?答案自然不是,为什么不是,看代码: /** * Replaces all linked nodes in bin at index for given hash unless * table is too small, in which case resizes instead. */ f