创建红黑树解决实际问题
在查找中,虽然hash表查找非常迅速,但是随着数据的种类增多,
hash表长会变得更长,且冲突也会越来越多,那么如何能实现无论在
多大数据量的情况下,查找依然是高性能的呢?
在1978年,Leo J.Guibas 与 Robert Sedgewick写了一篇论文中
谈到了一种较好的用于查找的数据结构----红黑树
一般来说,树是很好的一种数据结构,那用于插入,删除,查找等
都是很高效的数据树构,但问题是在很坏的情况下,操作很费时间,它的
性能得到不保证,比如二叉查找树中如果左子树与右子树相差太远,那么查找
时就很费时间。这时为了保证其有高效性,就得保证左树与右树不能差得太远,
当向树中插入时,就按一定规则调整,使其达到规则,从而使其整体与局部
查找效率得到提高。这就是红黑树的规则.
这些规则是
在二叉查找树的基础上,
(1)节点都有颜色,要么黑色,要么红色。
(2)根结点是黑色的,叶子结点是黑色的。
(3)每条从树到叶子的路上没有二个连续的红色。即红色的子树一定是黑色
(4)各条从叶子到根的路上的黑色结点相同。
关键的是(3), (4)它使得树是局部是平衡的,并且每条路线不会太长。
还有一个重要的点就是,为了研究方便,会在红黑树补成两个子树是完整的,
它们也有颜色,是黑色,但是没有数据,它称为nil叶子,null叶子。当搜索时
发现结点与nil叶子相 等时,则是找到了叶子了。
另外,关于红黑树与平衡二叉树的区别,它们的区别在概念上也有,
但是在性能上也有,平衡二叉树也是在最坏的情况下有高效的,但是它
追求整体的平衡,使得调整树时,会要很长的时间复杂度,而红黑树是
局部平衡,调整时只要0(logn)颜色变量,并且调整不超过三次。
那么如何使用红黑树来解决问题呢,可以先构造红黑树
构造红黑树的办法如下:
(1)定义节点结构,
一般是 值,key, 长度,左指针,右指针,指向父的指针,颜色。
(2)插入
插入时,先从树根开始,先校验树是不是为空节点或者nil结点,若是
则插入结点为新根,若不是,则与树比较,小于的话,往左移,大于
往右移,这里与二叉查找树类似,最后再对其颜色进行调整.所谓的调
整只有4种情况,都设计好了。
(3)查找
按照二叉查找树的样子进行查找。
例子:查找班上姓名为'xiaoming'同学的基本信息情况
办法: 则要以姓名为关键字建立一个红黑树,建法很多,
可以以其各字母ascii和的办法作为关键字,或以某函数生成一个均可。
然后树据关键字的值生成红黑树,再查找就可以了
部分MFC代码如下:
节点结构。
typedef struct Node
{
Coulor color;
int key;
Node *p,*left,*right;
int size;
char *name; //the description data that the node contained
}Node,*pNode;
下面的代码中,rbInsert(pNode z)为插入创建的函数,
void rbInsertFixUp(pNode z)为调整局部色彩的函数。
------------------
//RBTree.h文件如下
#ifndef RBTREE_H
#define RBTREE_H
#pragma once
#include
#include"MainFrm.h"
enum Coulor{RED,BLACK};
typedef struct Node
{
Coulor color;
int key;
Node *p,*left,*right;
int size;
char *name; //the description data that the node contained
}Node,*pNode;
extern Node Nil; //ÉÚ±ø
extern const pNode nil;
class rbTree
{
public:
pNode root;
pNode cur;
public:
rbTree(){root=cur=&Nil;};
void setName(pNode x,const char*na)
{
x->name=new char[strlen(na)+1];
strcpy(x->name,na);
}
pNode newNode(int k,const char*na="N",pNode pa=nil,pNode le=nil,pNode ri=nil)
{
pNode ne=new Node;
ne->key=k;
ne->color=RED;
ne->left=le;
ne->p=pa;
ne->right=ri;
ne->size=1;
setName(ne,na);
return ne;
}
//·ÃÎÊp,left,rightµÈ
pNode &p(pNode x){return x->p;};
pNode &left(pNode x){return x->left;};
pNode &right(pNode x){return x->right;};
int &size(pNode x){return x->size;};
Coulor &color(pNode x){return x->color;};
int &key(pNode x){return x->key;};
//
const pNode P(pNode x){return x->p;};
const pNode Left(pNode x){return x->left;};
const pNode Right(pNode x){return x->right;};
const int Size(pNode x){return x->size;};
const Coulor Color(pNode x){return x->color;};
const int Key(pNode x){return x->key;};
pNode successor(pNode x)
{
if(Right(x) != nil)
return minimum(Right(x));
pNode y= P(x);
while ( y!=nil && x==Right(y) )
{
x=y;
y=P(y);
}
return y;
}
//
pNode minimum( pNode x)
{
while (Left(x)!=nil)
x=Left(x);
return x;
}
int Bheight(pNode x)
{
pNode y=x;
int k=0;
while(y!=nil)
{
if(Color(y)==BLACK)
k++;
y=Left(y);
}
return k;
}
//×óÐýת
void lrotate(pNode x)
{
pNode y=Right(x);
//ά»¤size;
int sx=x->size;
int sy=y->size;
size(y)=sx;
size(x)=sx-size(Right(y))-1;
right(x)=Left(y);
p(Left(y))=x;
p(y)=P(x);
if(P(x)==nil)
{
root=y;
}
else if( x == Left(P(x)) )
{
left(P(y))=y;
}
else
right(P(x))=y;
left(y)=x;
p(x)=y;
}
//ÓÒÐýת
void rrotate(pNode x)
{
pNode y=Left(x);
//ά»¤size;
size(y)=Size(x);
size(x)=Size(x)-Size(Left(y))-1;
left(x)=Right(y);
p(Right(y))=x;
p(y)=P(x);
if(P(x)==nil)
{
root=y;
}
else if(x==Left(P(x)))
{
left(P(y))=y;
}
else
right(P(x))=y;
right(y)=x;
p(x)=y;
}
///
//²åÈë¼°Æäµ÷Õû
//²åÈë
void rbInsert(pNode z)
{
pNode y=nil;
pNode x=root;
while(x!=nil)
{
y=x;
size(x)=Size(x)+1;
if(Key(z) < Key(x))
x=Left(x);
else
x=Right(x);
}
p(z)=y;
if(y == nil)
root=z;
else if(Key(z)
left(y)=z;
else
right(y)=z;
rbInsertFixUp(z);
}
//µ÷Õû
void rbInsertFixUp(pNode z)
{
while(Color(P(z)) == RED)
{
if( P(z) == Left(P(P(z))))
{
pNode y=Right(P(P(z)));
if(Color(y) == RED)
{
color(P(z)) = BLACK;
color(y)= BLACK;
color(P(P(z))) =RED;
z=P(P(z));
}
else
{
if(z == Right(P(z)))
{
z=P(z);
lrotate(z);
}
color(P(z))=BLACK;
color(P(P(z)))=RED;
rrotate(p(P(z)));
}
}
else
{
pNode y=Left(P(P(z)));
if(Color(y) == RED)
{
color(P(z)) = BLACK;
color(y)= BLACK;
color(P(P(z))) =RED;
z=P(P(z));
}
else
{
if(z == Left(P(z)))
{
z=P(z);
rrotate(z);
}
color(P(z))=BLACK;
color(P(P(z)))=RED;
lrotate(p(P(z)));
}
}
}
color(root)=BLACK;
}
//
//ɾ³ý¼°Æäµ÷Õû
//ɾ³ý
pNode rbDelete(pNode z)
{
pNode x,y;
if(Left(z) == nil ||Right(z)==nil)
y=z;
else
y=successor(z);
if(Left(y) !=nil)
x=Left(y);
else
x=Right(y);
p(x)=P(y);
if(P(y) ==nil)
root=x;
else if(y==Left(P(y)) )
left(P(y))=x;
else
right(P(y))=x;
if(y!=z)
{
key(z)=Key(y);//
}
rbDeleteMaitainSize(y);
if(Color(y)==BLACK)
rbDeleteFixUp(x);
return y;
}
//µ÷Õû
void rbDeleteFixUp(pNode x)
{
while(x!=root && Color(x)==BLACK)
{
if(x ==Left(P(x)) )
{
pNode w=Right(P(x));
//case1
if(Color(w)==RED)
{
color(w)=BLACK;
color(P(x))=RED;
lrotate(P(x));
w=Right(P(x));
}
//case 2,3,4
if(Color(Left(w))==BLACK && Color(Right(w)) ==BLACK)
{
color(w)=RED;
x=P(x);
}
else if(Color(Right(w)) == BLACK)
{
color(Left(w))=BLACK;
color(w)=RED;
rrotate(w);
w=Right(P(x));
}
else
{
color(w)=Color(P(x));
color(P(x))=BLACK;
lrotate(P(x));
x=root;
}
}
else
{
pNode w=Left(P(x));
//case1
if(Color(w)==RED)
{
color(P(x))=RED;
rrotate(P(x));
w=Left(P(x));
}
//case 2,3,4
if(Color(Left(w))==BLACK && Color(Right(w)) ==BLACK)
{
color(w)=RED;
x=P(x);
}
else if(Color(Left(w)) == BLACK)
{
color(Right(w))=BLACK;
color(w)=RED;
lrotate(w);
w=Left(P(x));
}
else
{
color(w)=Color(P(x));
color(P(x))=BLACK;
rrotate(P(x));
x=root;
}
}
}
color(x)=BLACK;
}
/
//ά»¤size
void rbDeleteMaitainSize(pNode x)
{
cur=P(x);
while(cur!=nil)
{
size(cur)--;
cur=P(cur);
}
}
int Rank(pNode x)
{
int r= Size(Left(x))+1;
pNode y=x;
while(y!=root)
{
if( y == Right( P(y) ) )
{
r=r+Size(Left( P(y) ) )+1;
}
y=P(y);
}
return r;
}
pNode OS_Select(pNode x,int i)
{
if(i>Size(x))
return nil;
int r=Size(Left(x))+1;
if(i==r)
return x;
else if(i
return OS_Select(Left(x),i);
else
return OS_Select(Right(x),i-r);
}
friend class CMyWnd;//ÏÔʾºìºÚÊ÷µÄͼÐνçÃæÀࣻ
};
#endif
创建红黑树解决实际问题相关推荐
- 红黑树解决了什么问题
/*** 平衡二叉树:就是为了防止二叉搜索树变为线性数据结构,而出现的数据结构* 而AVL树-绝对平衡树.左右子树的高度差不能超过1* 红黑树:特性:* 1.每个结点不是红色就是黑色* 2.根节点:一 ...
- 红黑树探险:从理论到实践,一站式掌握C++红黑树
红黑树揭秘:从理论到实践,一站式掌握C++红黑树 引言 为什么需要了解红黑树? 红黑树在现代C++编程中的应用场景 树与平衡二叉搜索树 树的基本概念: 二叉搜索树的定义与性质: 平衡二叉搜索树的特点与 ...
- 死磕Java并:J.U.C之ConcurrentHashMap红黑树转换分析
作者:chessy 来源:Java技术驿站 在[死磕Java并发]-----J.U.C之Java并发容器:ConcurrentHashMap一文中详细阐述了ConcurrentHashMap的实现过程 ...
- ConcurrentHashMap的红黑树实现分析
转载自 ConcurrentHashMap的红黑树实现分析 红黑树 红黑树是一种特殊的二叉树,主要用它存储有序的数据,提供高效的数据检索,时间复杂度为O(lgn),每个节点都有一个标识位表示颜色,红色 ...
- 算法原理系列:红黑树
红黑树 看了网上关于红黑树的大量教程,发现一个共性,给出定义,适用情况,然后大量篇幅开始讨论它如何旋转,这就一发不可收拾了,各种情况的讨论,插入删除,插入删除,看的云里雾里,好不容易搞清楚,过段时间就 ...
- ConcurrentHashMap的红黑树
红黑树 红黑树是一种特殊的二叉树,主要用它存储有序的数据,提供高效的数据检索,时间复杂度为O(lgn), 每个节点都有一个标识位表示颜色,红色或黑色,有如下5种特性: 1.每个节点要么红色,要么是黑色 ...
- 关于二叉树、平衡二叉树、红黑树
目录 1.二叉树缺点 2.平衡二叉树 3.为什么有了平衡二叉树,还要红黑树? 参考文章:记一次腾讯面试:有了二叉查找树.平衡树(AVL)为啥还需要红黑树? 1.二叉树缺点 二叉查找树,相信大家都接触过 ...
- ConcurrentHashMap 红黑树转换分析
ConcurrentHashMap 红黑树转换分析 先看红黑树的基本概念:红黑树是一课特殊的平衡二叉树,主要用它存储有序的数据,提供高效的数据检索,时间复杂度为O(lgn).红黑树每个节点都有一个标识 ...
- 数据结构与算法 / 红黑树
一.定义 根节点是黑色的. 叶子节点是空的且是黑色的. 任何相邻的节点不能都为红色. 任意节点到其每个叶子节点的路径上,黑色的节点的数量相同. 二.性质 红黑树解决了 AVL 树增.删时耗时过大的问题 ...
最新文章
- linux vim模板,FreeBSD8下的vim配置模板
- 如何在eclipse中修改jsp默认编码
- 监控mysql主从复制监控_shell脚本监控mysql主从同步状态
- 与 python 交互
- RS 纠删码为什么可以提高分布式存储可靠性?| 原力计划
- TypeError: unorderable types: str() = int()
- 讨论 innodb_log_block_size 变量
- Python 这么热,运维要不要追赶 Python 的热潮?
- caffe上手:微调CaffeNet用于车颜色识别
- 关于消灭冲击波的蠕虫
- lammps学习总结3
- 341编程器 软硬件
- matlab建空数组,matlab数组的创建与操作
- 你绝没看如此详细的PDF去水印教程
- NB-IoT技术发展史漫谈(NB-IoT专栏—拓展篇1)
- 微信公众平台技术揭秘之Referer的妙用
- 国外html游戏发展历史,网页游戏技术发展史 早期到当前10几年历程
- java全角数字_Java全角、半角字符的关系以及转换
- 气质由内而外 都市白领3个饮食排毒法则
- 如何升级Windows 11正式版?四种方案都在这里了
热门文章
- oracle sqltune,DBMS_SQLTUNE
- 丝印代码html,丝印代码反查型号:ic上的丝印为HH1YA,封装是SOT23-6的,请问是什么型号呢?...
- 机器学习-分类模型-置信概率
- java url类_Java中的URL类和示例 - Break易站
- Python2.7获取QQ好友头像
- Random Forest和Gradient Tree Boosting模型如何调参
- 驱动程序安装方法大全(转)
- python微信支付接口_Python微信支付APIv3签名
- 1 win10双系统安装ubuntu16.04和18.04(问题详细记录)
- 怎么使用手机便签软件将图片上的文字扫描出来