RBTree 红黑树
红黑树
一、红黑树概述
红黑树不仅是一个二叉搜索树,并且满足以下规则:
1>每个节点不是红的就是黑的,
2>根结点为黑色,
3>如果节点为红色,其子节点必须为黑色,
4>任一节点至NULL(树尾端)的任何路径,所含的黑节点的树木必须相同
二、红黑树上结点的插入
下面分6种情况介绍红黑树的插入操作:
1 插入点的父亲为红,父亲的兄弟节点为黑,插入点在外侧 ///把父亲染红 祖父染黑 后右旋
2 插入点的父亲为红,父亲的兄弟节点为黑,插入点在内侧 ///先左旋后把父亲染红 祖父染黑 后右旋
3 插入点的父亲为红,父亲的兄弟节点为红,插入点在外侧 ///把父亲及父亲的兄弟染成黑色
4 插入点的父亲为红,父亲的兄弟节点为红,插入点在外侧 ///(父亲的祖父节点为红)
5 插入点的父亲为红,父亲的兄弟节点为红,插入点在内侧 ///先右旋父亲改为黑祖父为红后左旋(两次旋转)
6 插入点的父亲为黑,直接插入
这里判断父节点是否为祖先节点的左节点和 取得伯父节点,判断伯父节点的颜色的目的是为了识别以上者6种情况
针对双黑结点的兄弟做一次右旋转,结果使双黑结点的近侄子成为双黑结点新的兄弟;
将新兄弟结点着为双黑结点的父结点的颜色,父结点着为黑色,再针对父做一次左旋转,
三、红黑树删除操作
一、普通二叉查找树删除一个结点:
(1)待删除结点没有子结点,即它是一个叶子结点,此时直接删除
(2)待删除结点只有一个子结点,则可以直接删除;如果待删除结点是根结点,则它的子结点变为根结点;如果待删除结点不是根结点,则用它的子结点替代它的位置。
(3)待删除结点有两个子结点,首先找出该结点的后继结点(即右子树中数值最小的那个结点),然后将两个结点进行值交换(即:只交换两个结点的数值,不改变结点的颜色)并将待删除结点删除,由于后继结点不可能有左子结点,对调后的待删除结点也不会有左子结点,因此要把它删除的操作会落入情况(1)或情况(2)中。
二、.红黑树的删除结点算法
1.待删除结点有两个外部结点,操作如下:
(1)直接把该结点调整为叶结点
(2)若该结点是红色,则可直接删除,不影响红黑树的性质,算法结束
(3)若该结点是黑色,则删除后红黑树不平衡。此时要进行“双黑”操作
记该结点为V,则删除了V后,从根结点到V的所有子孙叶结点的路径将会比树中其他的从根结点到叶结点的路径拥有更少的黑色结点, 破坏了红黑树性质4。此时,用“双黑”结点来表示从根结点到这个“双黑”结点的所有子孙叶结点的路径上都缺少一个黑色结点。
双黑含义:该结点需要代表两个黑色结点,才能维持树的平衡
图1
如图1,要删除结点90,则删除后从根结点到结点90的所有子树结点的路径上的黑色结点比从根点到叶结点的路径上的黑结点少。因而,删除结点90后,用子结点NULL代替90结点,并置为“双黑”结点。
2. 待删除结点有一个外部结点,操作为:
该节点是黑色,其非空子节点为红色 ;则将其子节点提升到该结点位置,颜色变黑
3.“双黑”结点的处理
分三种情况:(1)双黑色结点的兄弟结点是黑色,且子结点有红色结点
(2)双黑结点的兄弟结点是黑色,且有两个黑色结点
处理方法:针对双黑结点的兄弟做一次右旋转,结果使双黑结点的近侄子成为双黑结点新的兄弟;将新兄弟结点着为双黑结点的父结点的颜色,父结点着为黑色,再针对父做一次左旋转,如图5
(2)双黑结点的兄弟结点是黑色,且有两个黑色结点,如图6
#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <stack>
#include <stdlib.h>
#include <windows.h> using namespace std; typedef int Elemtype;
#define RED 0
#define BLACK 1 typedef struct Node
{
Elemtype node;
struct Node* left;
struct Node* right;
struct Node* prev;
int color;
} Node, * PNode; typedef struct RBTree
{
PNode root;
PNode data;
} RBTree, * PRBTree; int init(PRBTree tree)
{ //红黑树的初始化
if(tree == NULL) {
return ;
}
tree->data = (PNode)malloc(sizeof(Node));
tree->data->color = BLACK;
tree->root = tree->data;
return ;
}
void rotate_left(PRBTree tree, PNode x)
{
PNode y = x->right;
x->right = y->left;
if(y->left != tree->data)
{
y->left->prev = x;
}
y->prev = x->prev;
if(x == tree->root) {
tree->root = y;
}
else if(x == x->prev->left) {
x->prev->left = y;
}
else {
x->prev->right = y;
}
y->left = x;
x->prev = y;
} ///右旋
void rotate_right(PRBTree tree, PNode x)
{
PNode y = x->left;
x ->left = y->right;
if(y->right != tree->data)
{
y->right->prev = x;
}
y->prev = x->prev;
if(x == tree->root) {
tree->root = y;
}
else if(x == x->prev->left) {
x->prev->left = y;
}
else {
x->prev->right = y;
}
y->right = x;
x->prev = y;
} int insert_fixup(PRBTree tree, PNode e)
{
while(e->prev->color == RED)
{
if(e->prev->prev->left == e->prev) ///该节点的父亲节点是 左节点
{
if(e->prev->prev->right == RED)
{
e = e->prev->prev;
e->left->color = e->right->color = BLACK;
e->color = RED;
}
else
{
if(e->prev->right == e)
{
e = e->prev;
rotate_left(tree, e);
}
e->prev->color = BLACK;
e->prev->prev->color = RED;
rotate_right(tree, e->prev->prev);
}
}
else ///该节点的父亲节点是 右节点
{
if(e->prev->prev->left->color == RED)
{
e = e->prev->prev;
e->left->color = e->right ->color = BLACK;
e->color = RED;
}
else
{
if(e->prev->left == e)
{
e = e->prev;
rotate_right(tree, e);
}
e->prev->color = BLACK;
e->prev->prev->color = RED;
rotate_left(tree, e->prev->prev);
}
}
}
tree->root->color = BLACK;
return ;
} PNode insertNode(PRBTree tree, Elemtype e)
{
PNode t = NULL;
PNode p = NULL;
t = tree->root;
int flag = ;
if(tree->root == tree->data)
{
tree->root = (PNode)malloc(sizeof(Node));
tree->root->node = e;
tree->root->color = BLACK;
tree->root->prev = tree->root->left = tree->root->right = tree->data;
return tree->root;
}
while(t != tree->data)
{
p = t;
if(e < t->node)
{
flag = ;
t = t->left;
}
else
{
if(e > t->node)
{
flag = ;
t = t ->right;
}
else
{
if((flag = rand() % ) == )
{
t = t->left;
}
else
{
t = t->right;
}
}
}
}
t = (PNode)malloc(sizeof(Node));
t->node = e;
t->color = RED;
t->prev = p;
t->left = t->right = tree->data;
if(!flag)
{
p->left = t;
}
else
{
p->right = t;
}
insert_fixup(tree, t);
return t;
} ///左旋 ///找后继结点中-->右子树中数值最小的节点
PNode next(PRBTree tree, PNode t)
{
if(t == tree->data)
{
return NULL;
}
while(t->right != tree->data);
{
t = t->right;
}
return t;
} int delete_fixup(PRBTree tree, PNode c)
{
PNode b;
while(c != tree->root && c->color == BLACK)
{
if(c == c -> prev->left)
{
b = c->prev->right;
if(b->color == RED)
{
b->color = BLACK;
c->prev->color = RED;
rotate_left(tree, c->prev);
b = c->prev->right;
}
if(b->right->color == BLACK && b->left->color == BLACK)
{
b->color = RED;
c = c->prev;
}
else
{
if(b->right->color == BLACK)
{
b->color = RED;
b->left->color = BLACK;
rotate_right(tree, b);
b = c->prev->right;
}
b->color = b->prev->color;
b->prev->color = BLACK;
b->right->color = BLACK;
rotate_left(tree, c->prev);
c = tree->root;
}
}
else
{
b = c->prev->left;
if(b->color == RED)
{
b->color = BLACK;
c->prev->color = RED;
rotate_right(tree, c->prev);
b = c->prev->left;
}
if(b->right->color == BLACK && b->left->color == BLACK)
{
b->color = RED;
c = c->prev;
}
else
{
if(b->left->color == BLACK)
{
b->color = RED;
b->right->color = BLACK;
rotate_left(tree, b);
b = c->prev->left;
}
b->color = b->prev->color;
b->prev->color = BLACK;
b->left->color = BLACK;
rotate_right(tree, c->prev);
c = tree->root;
}
}
}
c->color = BLACK;
return ;
} ///删除节点
PNode destory_node(PRBTree tree, PNode t)
{
PNode c = NULL;
PNode d = NULL;
Elemtype tmp;
if(t == tree->data)
{
return NULL;
}
if(t->left != tree->data && t->right != tree->data) ///该节点有两个子节点 则找到该节点右子树中最小的值
{
d = next(tree, t);
tmp = d->node;
d->node = t->node;
t->node = tmp;
}
else
{
d = t;
}
if(d->left == tree->data)
{
c = d->right;
}
else
{
c = d->left;
}
c->prev = d->prev;
if(d->prev != tree->data)
{
if(d->prev->left == d)
{
d->prev->left = c;
}
else
{
d -> prev->right = c;
}
}
else
{
tree->root = c;
}
if(d->color == BLACK)
{
delete_fixup(tree, c);
}
return d;
} ///最小值
int minnum(PRBTree tree)
{
PNode x = tree->root;
while(x->left != tree->data)
{
x = x->left;
}
return x->node;
}
int get_root(PRBTree tree)
{
PNode x = tree->root;
return x->node;
}
///最大值
int maxnum(PRBTree tree)
{
PNode x = tree->root;
while(x->right != tree->data)
{
x = x->right;
}
return x->node;
} PNode mmap[];
void print(PRBTree tree)
{
PNode x = tree->root;
int front = ;
int rear = ;
if(tree == NULL)
{
printf("NULL\n");
return;
}
PNode tmp;
mmap[rear] = x;
int count = ;
int temp = ;
while(front <= rear)
{
tmp = mmap[front++];
count--;
if(tmp->left != tree->data)
{
mmap[++rear] = tmp->left;
temp++;
}
if(tmp->right != tree->data)
{
mmap[++rear] = tmp->right;
temp++;
}
printf("%d color = -->", tmp->node);
if(tmp->color == BLACK)
{
printf("BLACK |");
}
else
{
printf("RED |");
}
if(count == )
{
count = temp;
temp = ;
printf("\n");
}
}
return ;
}
PNode get_root1(PRBTree tree)
{
return tree->root;
}
int main()
{
PNode p ;
RBTree tree ;
init(&tree);
int i;
PNode tt , ttt;
tt = insertNode(&tree, );
insertNode(&tree, );
insertNode(&tree, );
insertNode(&tree, );
insertNode(&tree, );
insertNode(&tree, );
insertNode(&tree, );
insertNode(&tree, );
insertNode(&tree, );
insertNode(&tree, );
insertNode(&tree, );
insertNode(&tree, );
p = get_root1(&tree);
printf("根是------>%d\n", get_root(&tree));
printf("根是------>%d\n\n", p->node);
int mmin = minnum(&tree);
int mmax = maxnum(&tree);
printf("mmin = %d\n", mmin);
printf("mmax = %d\n\n", mmax);
print(&tree);
printf("\n删除 %d 之后树的结构是:\n\n", tt->node);
ttt = destory_node(&tree, tt);
print(&tree);
return ;
}
输出结果是:
根是------>
根是------> mmin =
mmax = color = -->BLACK |
color = -->BLACK | color = -->BLACK |
color = -->BLACK | color = -->BLACK | color = -->RED | color = -->RED |
color = -->BLACK | color = -->BLACK | color = -->BLACK | color = -->BLACK |
color = -->RED | 删除 之后树的结构是: color = -->BLACK |
color = -->BLACK | color = -->BLACK |
color = -->BLACK | color = -->RED | color = -->BLACK | color = -->BLACK |
color = -->RED | color = -->BLACK | color = -->BLACK | color = -->RED |
RBTree 红黑树的更多相关文章
- 红黑树(二)之 C语言的实现
概要 红黑树在日常的使用中比较常用,例如Java的TreeMap和TreeSet,C++的STL,以及Linux内核中都有用到.之前写过一篇文章专门介绍红黑树的理论知识,本文将给出红黑数的C语言的实现 ...
- 红黑树的C语言实现
rbtree.h #ifndef _RED_BLACK_TREE_H_ #define _RED_BLACK_TREE_H_ #define RED 0 // 红色节点 #define BLACK 1 ...
- 平衡搜索树--红黑树 RBTree
红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是Red或Black. 通过对任何一条从根到叶子节点简单路径上的颜色来约束树的高度,红黑树保证最长路径不超过最短路径的两倍, ...
- java——红黑树 RBTree
对于完全随机的数据,普通的二分搜索树就很好用,只是在极端情况下会退化成链表. 对于查询较多的情况,avl树很好用. 红黑树牺牲了平衡性,但是它的统计性能更优(综合增删改查所有的操作). 红黑树java ...
- 红黑树(RBTREE)之上-------构造红黑树
该怎么说呢,现在写代码的速度还是很快的,很高兴,o(^▽^)o. 光棍节到了,早上没忍住,手贱了一般,看到*D的优惠,买了个机械键盘,晚上就到了,敲着还是很舒服的,和老婆炫耀了一把哈哈. 光棍节再去* ...
- 红黑树(RB-tree)比AVL树的优势在哪?
1. 如果插入一个node引起了树的不平衡,AVL和RB-Tree都是最多只需要2次旋转操作,即两者都是O(1):但是在删除node引起树的不平衡时,最坏情况下,AVL需要维护从被删node到root ...
- 高级搜索树-红黑树(RBTree)代码实现
代码实现 代码参考了<数据结构(c++语言版)>--清华大学邓俊辉 "RBTree.h" #pragma once //#include"pch.h" ...
- 高级搜索树-红黑树(RBTree)解析
目录 红黑树的定义 节点与树的定义 旋转操作 插入操作 情况1:p的兄弟u为黑色 情况2: p的兄弟u为红色 插入操作性能分析 代码实现 删除操作 情况1:x的接替者succ为红色 情况2:x的接替者 ...
- RB-tree (红黑树)相关问题
今天被问到了红黑树的规则,简述总结一下: 1.每个节点不是红色就是黑色. 2.根节点为黑色. 3.如果节点为红,其子节点必须为黑. 4.任一节点至NULL(树尾端)的任何路径,所含之黑节点数必须相同. ...
随机推荐
- Coursera: Internet History, Technology, and Security
课程网址:https://www.coursera.org/learn/internet-history 学习笔记: Week 1: History - Dawn of Early Computing ...
- 基于bootstrap动态分页
bootstrap本身的分页有分页组件 但是却是静态的,无法满足要求,分页必须根据当前的总页数来展示 使用插件bootstrap-paginator github下载地址 https://github ...
- Struts2值栈
一.前言 很多事儿啊,就是“成也萧何败也萧何”,细想一些事儿心中有感,当然,感慨和本文毛关系都没有~想起之前有篇Struts2中值栈的博客还未完工,就着心中的波澜,狂咽一把~ 二.正文 博文基于:st ...
- [C/C++] C++声明和定义的区别
·变量定义:用于为变量分配存储空间,还可为变量指定初始值.程序中,变量有且仅有一个定义. ·变量声明:用于向程序表明变量的类型和名字. ·定义也是声明:当定义变量时我们声明了它的类型和名字. ·ext ...
- mac --snip 滚动截屏
1.snip 下载配置:https://jingyan.baidu.com/article/fec4bce2458d03f2618d8b8e.html 2.mac的火狐浏览器好像不支持,必须在sofa ...
- Springboot2.0 集成shiro权限管理
在springboot中结合shiro教程搭建权限管理,其中几个小细节的地方对新手不友好,伸手党更是无法直接运行代码,搭建过程容易遇坑,记录一下.关键的地方也给注释了. 版本:springboot版本 ...
- 解决IIS设置多个工作进程中Session失效的问题
利用StateServer实现Session共享 session保存在专门的StateServer中,该种方式,性能损失比sql略好.比inproc据说有10%-15%的性能损失.怎么使用StateS ...
- VK Cup 2016 - Round 1 (Div. 2 Edition) A Bear and Reverse Radewoosh
A. Bear and Reverse Radewoosh time limit per test 2 seconds memory limit per test 256 megabytes inpu ...
- Google File System中文版
英文原文地址: Google File system 译文原文地址: The Google File System中文版 Google File System中文版 摘要 我们设计并实现了Google ...
- Python基础(4)_集合、布尔类型
一.集合 集合的作用一:关系运算集合的作用二:去重 定义集合:集合内的元素必须是唯一的:集合内的元素必须是可hash的,也是就不可变类型:集合是无序的 s={'egon',123,'egon','1' ...