`
ssxxjjii
  • 浏览: 948285 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

漫游红黑树之插入篇

 
阅读更多

http://www.cnblogs.com/xuqiang/archive/2011/05/16/2047001.html

 

<1>. 红黑树简介 

红黑树是一种平衡的二叉查找树,是一种计算机科学中常用的数据结构,最典型的应用是实现数据的关联,例如map等数据结构的实现。1972年,鲁道夫贝尔最先发明,但是他称之为“对称二叉B树”,真正的称之为“红黑树”是在1978年Leo J. Guibas 和 Robert Sedgewick的一篇论文开始的。这么算起来,红黑树已经存在了将近30年,时至今日,仍旧另初学者头痛不已。

<2>. 性质简介

红黑树拓展了二叉查找树,给每个树的节点增加了一个Color属性,每个节点必须是红色或者是黑色,另外为了达到树的平衡,增加了如下的限制(下面是用“限制”来指明):

1. 节点必须是红色或者是黑色

2. 根节点是黑色的,如果不是黑色,根据下面的性质4,将无法插入新节点

3. 所有的叶子节点是黑色的,这里可以增加哨兵元素,作为叶子节点,该节点是黑色,也就是说该条件是一定满足的。

4. 每个红色节点的两个子节点是黑色的,也就是不能存在父子两个节点全是红色

5. 从任意每个节点到其每个叶子节点的所有简单路径上黑色节点的数量是相同的。

上面的这些约束保证了这个树大致上是平衡的,这也决定了红黑树的插入,删除,查询等操作是比较快速的。 

<3>. 漫游红黑树 

很多初学者在学习红黑树时,总是首先查看别人的思路(比如《算法导论》等),然后基本上就陷入了泥潭,那么我们不妨静下心来自己想一想如果我去实现需要该怎么做?好的,准备好,开始漫游红黑树的?这里不仅仅是列出插入操作分为那些情况,更重要的是知道问什么这么分类?

好的,现在我们是一无所有,假设这是第一次插入一个节点,为了满足上面的1-5条性质,很显然仅仅需要很少量的操作即可:

生成一个新节点,并拷贝数据;

节点颜色表明为黑色;

 通过上面的操作生成的只有一个节点的树,满足1-5条性质,显然该树是红黑树。

 

 特殊情况考虑完成之后,下面假设又开始添加节点,我们面对的第一个问题是新增加的节点是标记成红色还是黑色?显然无论是新插入的节点是黑色或者是红色,红黑树限制1,2,3一定是满足的,那么如果将新插入的节点标识成黑色的话,可能违反5,但是如果将新插入的节点标识成红色,肯能违反4,看似好像是两个是类似的。

但是考虑这样的一种情况:如果新插入的节点标识成红色,并且新插入的节点的父节点是黑色,那么是违反性质4的,也就是说是不需要重新调整红黑树的。

 

但是如果标识成黑色的话,那么是一定会违反性质5,好的,我们还是选择将插入的节点标识成红色吧,至少运气好的话,就不需要重新调整红黑树了。 

 确定了新插入的节点的颜色之后,现在开始具体的实现插入操作,由于红黑树实际上也是一种二叉查找树,那么新插入的顶点一定是在红黑树的最低端,我们忽略掉这个查找节点的过程,这里仅仅关心插入节点之后如何调整红黑树。数学上的常用方法:分类讨论

case 1. 如果插入的节点是根节点,也就是说初始的红黑树为空,这是最简单的情况,直接将该节点标识成黑色即可。

复制代码
 void insert_case1(struct node *n) 
{

        if (n->parent == NULL)
                n->color = BLACK;
        
else
                insert_case2(n);
}

复制代码

case 2. 如果新插入的节点不是红黑树的根节点,如果新插入的节点的父节点是黑色的话,那么红黑树是不需要调整的

 

代码:

复制代码
void insert_case2(struct node *n)
{
        
if (n->parent->color == BLACK)
                
return/* Tree is still valid */
        
else
                insert_case3(n);
} 
复制代码

case 3. 如果新插入的节点的父节点是红色的话,显然这里违反了红黑树中不能存在父节点和子节点同时为红色的性质,。

 

于是需要调整,我们的调整的目标是在不违反红黑树性质(或者是可调整)如何将两个相邻的红色节点分隔开来,显然最终的结果是我们需要将新插入的节点的父节点更改成黑色(新插入节点是如法作出调整的,实现将两个红色节点分割开的,除非将该节点标识为黑色,但是这会增加黑高度),但是如果是单纯的修改父节点为黑色的话,那么将会违背黑色顶点数目的性质,直接修改是行不通,那么能否通过交换两个两个节点达到目的呢?

显然新插入的节点的祖父节点一定是黑色的,那么是否能够通过交换父节点和祖父节点的红黑性质来达到目的呢?显然这可能违反将新插入节点的叔叔子树的红黑树性质破坏掉。但是如果叔叔节点是红色的话,问题似乎变得很简单了。 

 

我们仅仅需要将主父节点改成红色,同时将父节点和叔叔节点改成黑色即可。

 

但是这将引入新的问题, 显然我们将G节点表示成红色之后,那么G节点和G的父节点是可能违反红黑性质的,为了解决这个问题,这里使用尾递归的形式来对节点G进行调整。

复制代码
void insert_case3(struct node *n)
{
        
struct node *= uncle(n), *g;
 
        
if ((u != NULL) && (u->color == RED)) {
                n
->parent->color = BLACK;
                u
->color = BLACK;
                g 
= grandparent(n);
                g
->color = RED;
                insert_case1(g);
        } 
else {
                insert_case4(n);
        }

}  

复制代码

一种情况已经解决。下面将是更加艰巨的任务,如果叔叔节点是黑色的,该如何是好?

 case 4:我们来看看还剩下的就是这种情况了,P为红色,U为黑色,G为黑色,怎么解决?对了,到这里是否忘了我们的最终目的是什么?

 在不违反红黑树性质(或者是可调整)如何将两个相邻的红色节点分隔开来. 

 

 

直接将P节点修改成黑色是不行的,这将增加G-P-U路径上的黑高度, 没有思路,好的,来回头看看case 3的情况,毕竟已经解决了一种情况,case 3中我们修改了节点G的颜色,为什么能够修改,显然是说G是最顶点(辈份最高)的节点,最顶点的节点的颜色可以是红色(重新调整)或者是黑色。

那如果我们呢将P节点提升至现在G的位置呢(通过树的旋转)?

 

现在可以将P的颜色标识成黑色,但是会破坏P-G-U的黑路径,运用一下交换的思想吧,交换P和G的颜色即可。

现在基本上已经解决了红黑树中如果叔叔是黑色的情况,剩下的工作就是分析旋转方向,根据节点P和N是左孩子还是右孩子进行相应旋转。

这是case 4情况:

 

或者是:

 

复制代码
void insert_case4(struct node *n)
{
        
struct node *= grandparent(n);
 
        
if ((n == n->parent->right) && (n->parent == g->left)) {
                rotate_left(n
->parent);
                n 
= n->left;
        } 
else if ((n == n->parent->left) && (n->parent == g->right)) {
                rotate_right(n
->parent);
                n 
= n->right;
        }
        insert_case5(n);
} 
复制代码

这样将P和U不再同一条直线的情景转换成在统一条直线上的情况,case 5我们处理在同一条直线上的情况:

case 5:

 

或者是:

 

复制代码
void insert_case5(struct node *n)
{
        
struct node *= grandparent(n);
 
        n
->parent->color = BLACK;
        g
->color = RED;
        
if ((n == n->parent->left) && (n->parent == g->left)) {
                rotate_right(g);
        } 
else { /* (n == n->parent->right) and (n->parent == g->right) */
                rotate_left(g);
        }

}  

复制代码

红黑树的插入的所有情况分析完了,也就是说我们的分类讨论是完整的吗?

 

好的,看来我们穷举了所有的红黑树的插入情况,红黑树插入漫游完毕。 这里有一个applet的动画演示,很生动。

<4>. 我的EasyCoding库 

最后说一说现在正在开发的一个基于c#语言算法实现库吧,正在开发之中,还存在很多技术上的难点(对我这种菜鸟而言),我给这个项目名了个不是很响亮的名字EasyCoding,基本的项目的结构:

 

Collections中主要是一些数据结构的实现,现在已经完成了Bag,Association,BinarySearchTree,HashList,Heap,PriorityQueue,VisitableHashtable,

VisitableLinkedList

,VisitableList,VisitableQueue,VisitableStack这些集合类,有一些是对.net集合类的重新封装,例如Visitable-XXX集合类的话,其内部使用的是.net提供的集合类,但是重新实现了访问者模式(主要是为了集合类的功能的拓展性),下面是Test项目中的一段代码,演示的是如何使用访问者模式对集合类进行功能拓展:

复制代码
        [Test]
public void TestVisitor()
        {
            VisitableStack
<int> stack = new VisitableStack<int>();
            stack.Push(
2);
            stack.Push(
4);
            stack.Push(
9);
            stack.Push(
3);

            ComparableFindingVisitor
<int> visitor = new ComparableFindingVisitor<int>(9);
            stack.Accept(visitor);

            Assert.AreEqual(visitor.Found, 
true);

            visitor 
= new ComparableFindingVisitor<int>(5);
            stack.Accept(visitor);
            Assert.AreEqual(visitor.Found, 
false);
        }
复制代码

 接下来打算开始实现一些比较复杂的数据结构,例如这里的红黑树,avl树,跳表,FibonacciHeap,图的顶层存储容器等。

Algorithm主要是算法库的实现,暂时完成了一些简单的排序算法,打算添加一些搜索算法和图论常见算法;

Test项目使用的是unuit测试框架对Collection和Algorithm进行测试;

Visualization主要是想完成数据结构和算法的可视化运行,暂时还未开始(技术上不熟练啊),打算是使用silverllght来做。

 

路漫漫其修远兮,继续吧。

<5>. 参考资料及代码下载 

http://libredblack.sourceforge.net/ 

红黑树动态演示:http://secs.ceas.uc.edu/~franco/C321/html/RedBlack/redblack.html 

http://gauss.ececs.uc.edu/RedBlackTester/redblack.html 

http://www.cs.auckland.ac.nz/~jmor159/PLDS210/red_black.html 

http://www.cs.auckland.ac.nz/~jmor159/PLDS210/red_black_op.html

http://zh.wikipedia.org/wiki/%E7%BA%A2%E9%BB%91%E6%A0%91 

http://blog.csdn.net/v_JULY_v/archive/2010/12/29/6105630.aspx 

http://en.wikipedia.org/wiki/Red-black_tree#Operations 

分享到:
评论

相关推荐

    Cesium飞行漫游 Cesium飞行漫游

    Cesium飞行漫游Cesium飞行漫游Cesium飞行漫游Cesium飞行漫游Cesium飞行漫游Cesium飞行漫游Cesium飞行漫游Cesium飞行漫游Cesium飞行漫游Cesium飞行漫游Cesium飞行漫游Cesium飞行漫游Cesium飞行漫游Cesium飞行漫游...

    cesium之三维漫游飞行效果实现篇.zip

    在本篇中,我们将深入探讨如何使用Cesium实现三维漫游飞行效果。Cesium是一款强大的开源JavaScript库,专为在Web上创建交互式、实时3D地理空间应用程序而设计。它利用 WebGL 技术,无需插件即可在浏览器中展示全球高...

    wlan漫游实现,ac间三层漫游

    在无线局域网络(WLAN)中,漫游是指移动设备如智能手机或笔记本电脑在不同接入点(Access Point, AP)之间切换以保持最佳的网络连接。"ac间三层漫游"是WLAN漫游的一种高级形式,涉及到多个接入控制器(Access ...

    wlan无线漫游 实验配置

    WLAN漫游是指STA在不同AP覆盖范围之间移动且保持用户业务不中断的行为。 WLAN漫游是指STA在不同AP覆盖范围之间移动且保持用户业务不中断的行为。如图所示,STA从AP1的覆盖范围移动到AP2的覆盖范围时保持业务不中断。...

    实战华为无线 21.漫游系列(8)不同AC之间三层漫游

    本篇将详细讲解华为无线解决方案中的“不同AC之间三层漫游”技术,适用于二层上线、直连式以及隧道转发模式,针对相同VLAN但不同子网的环境。 首先,我们来理解“三层漫游”的概念。在无线网络中,当AP(接入点)...

    三维地形漫游论文十篇

    3、三维地形的实时绘制与漫游.pdf 4、三维地形可视化及其实时显示方法概论.pdf 5、三维地形生成及其可视化处理研究.pdf 6、三维地形真实感绘制及其实时漫游.pdf 7、三维分形地形生成技术综述.pdf 8、三维数字地形...

    教室漫游_opengl漫游_opengl_漫游_

    在这个"教室漫游"项目中,我们利用OpenGL来创建一个简单的教室环境,让用户可以自由地在虚拟教室中进行漫游。 首先,我们需要了解OpenGL的基础知识。OpenGL是一个跨语言、跨平台的编程接口,用于生成2D和3D图像。它...

    实战华为无线 20. 漫游系列(7)不同AC之间二层漫游

    本篇将深入探讨“实战华为无线 20. 漫游系列(7)不同AC之间二层漫游”的相关知识点。 一、二层漫游的概念 二层漫游是指在同一VLAN下的漫游,设备在移动过程中无需经过路由过程,直接在同一个广播域内进行通信。...

    WLAN漫游技术介绍

    WLAN漫游技术是无线网络中一项重要的技术,它允许用户在无线局域网(WLAN)中自由移动而不间断地使用网络服务。WLAN漫游通常发生在无线用户设备(如智能手机、平板电脑和笔记本电脑)从一个接入点(AP)移动到另一个...

    华为ac6605组网三层漫游

    【华为AC6605组网三层漫游详解】 在无线网络部署中,华为AC6605(Access Controller)是常用于企业级无线局域网(WLAN)的控制器,它能有效地管理AP(Access Point)并实现高效、安全的无线覆盖。三层漫游是指在...

    Cesium自定义路径飞行漫游

    基于Cesium1.62开发的三维场景漫游,动态移动视角,采集运动节点信息,自动漫游回放

    OpenGL3D模型场景漫游

    3D场景漫游、 树和水波纹、 键盘操纵漫游。 包含光照 贴图。

    漫游展示制作系统--漫游大师

    【漫游展示制作系统--漫游大师】是一款专为用户设计的简单易用的软件工具,主要用于创建高质量的三维漫游展示。这款软件的核心功能在于将三维建模技术与交互式体验相结合,使得用户能够轻松地构建虚拟环境,提供沉浸...

    空间漫游 C++ 虚拟漫游

    用C++做的虚拟漫游的小例子 供正在学习漫游的童鞋学习交流

    three.js自定义路径漫游

    基于three.js封装的自定义漫游小代码,传入最少两点三维坐标,即可实现飞行漫游。

    全景漫游正式版

    “易捷全景漫游”是三维全景行业领先的三维全景虚拟漫游展示制作软件,将三维全景图、平面地图、百度地图或者多种类型图片与声音、视频、flash等多媒体元素相结合,以及通过在场景中添加热点、在地图上添加雷达,...

    元宇宙初探React+Three.js制作3D全景漫游.zip

    元宇宙初探React+Three.js制作3D全景漫游.zip元宇宙初探React+Three.js制作3D全景漫游.zip元宇宙初探React+Three.js制作3D全景漫游.zip元宇宙初探React+Three.js制作3D全景漫游.zip元宇宙初探React+Three.js制作3D...

    实战华为无线 17.漫游系列(4)同一AC内AP之间三层漫游

    在本知识点中,我们将详细探讨华为无线网络中,同一接入控制器(AC)内不同接入点(AP)之间的三层漫游过程。首先,让我们了解三层漫游的概念以及它在无线网络中的作用。 三层漫游指的是在同一AC管理下的不同AP之间...

    Unity3d中简单场景漫游的制作

    本篇文章将指导读者从零开始创建一个简单的场景漫游游戏,涵盖模型准备、模型导出、Unity 项目创建、模型导入、地形创建、光照效果等多个方面。 在本篇文章中,我们首先需要准备一个 3D 模型,使用 Maya 软件创建一...

Global site tag (gtag.js) - Google Analytics