`
kongweile
  • 浏览: 523260 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

漫游红黑树之插入篇

 
阅读更多

<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 

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

转:

分享到:
评论

相关推荐

    数据结构课程设计个人账簿管理系统

    而二叉树(如AVL树或红黑树)可能用于高效地查找特定日期或金额的交易。 在这个个人账簿管理系统中,可能会涉及到以下关键知识点: 1. **数据结构**:理解各种数据结构(如数组、链表、树、图等)的特性,选择适合...

    数据结构课程设计宿舍管理查询系统

    另外,查找特定宿舍或学生的快速方法,可以采用平衡搜索树,如AVL树或红黑树。 6. **图**:如果要考虑学生之间的关系或宿舍间的关联,如室友关系,图结构能直观地表示这些复杂的关系。可以使用邻接矩阵或邻接表来...

    SNS单模无芯光纤仿真与传感器结构特性分析——基于Rsoft beamprop模块

    内容概要:本文主要探讨了SNS单模无芯光纤的仿真分析及其在通信和传感领域的应用潜力。首先介绍了模间干涉仿真的重要性,利用Rsoft beamprop模块模拟不同模式光在光纤中的传播情况,进而分析光纤的传输性能和模式特性。接着讨论了光纤传输特性的仿真,包括损耗、色散和模式耦合等参数的评估。随后,文章分析了光纤的结构特性,如折射率分布、包层和纤芯直径对性能的影响,并探讨了镀膜技术对光纤性能的提升作用。最后,进行了变形仿真分析,研究外部因素导致的光纤变形对其性能的影响。通过这些分析,为优化光纤设计提供了理论依据。 适合人群:从事光纤通信、光学工程及相关领域的研究人员和技术人员。 使用场景及目标:适用于需要深入了解SNS单模无芯光纤特性和优化设计的研究项目,旨在提高光纤性能并拓展其应用场景。 其他说明:本文不仅提供了详细的仿真方法和技术细节,还对未来的发展方向进行了展望,强调了SNS单模无芯光纤在未来通信和传感领域的重要地位。

    发那科USM通讯程序socket-rece

    发那科USM通讯程序socket-set

    嵌入式八股文面试题库资料知识宝典-WIFI.zip

    嵌入式八股文面试题库资料知识宝典-WIFI.zip

    JS+HTML源码与image

    源码与image

    物流行业车辆路径优化:基于遗传算法和其他优化算法的MATLAB实现及应用

    内容概要:本文详细探讨了物流行业中路径规划与车辆路径优化(VRP)的问题,特别是针对冷链物流、带时间窗的车辆路径优化(VRPTW)、考虑充电桩的车辆路径优化(EVRP)以及多配送中心情况下的路径优化。文中不仅介绍了遗传算法、蚁群算法、粒子群算法等多种优化算法的理论背景,还提供了完整的MATLAB代码及注释,帮助读者理解这些算法的具体实现。此外,文章还讨论了如何通过MATLAB处理大量数据和复杂计算,以得出最优的路径方案。 适合人群:从事物流行业的研究人员和技术人员,尤其是对路径优化感兴趣的开发者和工程师。 使用场景及目标:适用于需要优化车辆路径的企业和个人,旨在提高配送效率、降低成本、确保按时交付货物。通过学习本文提供的算法和代码,读者可以在实际工作中应用这些优化方法,提升物流系统的性能。 其他说明:为了更好地理解和应用这些算法,建议读者参考相关文献和教程进行深入学习。同时,实际应用中还需根据具体情况进行参数调整和优化。

    嵌入式八股文面试题库资料知识宝典-C and C++ normal interview_8.doc.zip

    嵌入式八股文面试题库资料知识宝典-C and C++ normal interview_8.doc.zip

    基于灰狼优化算法的城市路径规划Matlab实现——解决TSP问题

    内容概要:本文介绍了基于灰狼优化算法(GWO)的城市路径规划优化问题(TSP),并通过Matlab实现了该算法。文章详细解释了GWO算法的工作原理,包括寻找猎物、围捕猎物和攻击猎物三个阶段,并提供了具体的代码示例。通过不断迭代优化路径,最终得到最优的城市路径规划方案。与传统TSP求解方法相比,GWO算法具有更好的全局搜索能力和较快的收敛速度,适用于复杂的城市环境。尽管如此,算法在面对大量城市节点时仍面临运算时间和参数设置的挑战。 适合人群:对路径规划、优化算法感兴趣的科研人员、学生以及从事交通规划的专业人士。 使用场景及目标:①研究和开发高效的路径规划算法;②优化城市交通系统,提升出行效率;③探索人工智能在交通领域的应用。 其他说明:文中提到的代码可以作为学习和研究的基础,但实际应用中需要根据具体情况调整算法参数和优化策略。

    嵌入式八股文面试题库资料知识宝典-Intel3.zip

    嵌入式八股文面试题库资料知识宝典-Intel3.zip

    嵌入式八股文面试题库资料知识宝典-2019京东C++.zip

    嵌入式八股文面试题库资料知识宝典-2019京东C++.zip

    嵌入式八股文面试题库资料知识宝典-北京光桥科技有限公司面试题.zip

    嵌入式八股文面试题库资料知识宝典-北京光桥科技有限公司面试题.zip

    物理学领域十字形声子晶体的能带与传输特性研究及应用

    内容概要:本文详细探讨了十字形声子晶体的能带结构和传输特性。首先介绍了声子晶体作为新型周期性结构在物理学和工程学中的重要地位,特别是十字形声子晶体的独特结构特点。接着从散射体的形状、大小、排列周期等方面分析了其对能带结构的影响,并通过理论计算和仿真获得了能带图。随后讨论了十字形声子晶体的传输特性,即它对声波的调控能力,包括传播速度、模式和能量分布的变化。最后通过大量实验和仿真验证了理论分析的正确性,并得出结论指出散射体的材料、形状和排列方式对其性能有重大影响。 适合人群:从事物理学、材料科学、声学等相关领域的研究人员和技术人员。 使用场景及目标:适用于希望深入了解声子晶体尤其是十字形声子晶体能带与传输特性的科研工作者,旨在为相关领域的创新和发展提供理论支持和技术指导。 其他说明:文中还对未来的研究方向进行了展望,强调了声子晶体在未来多个领域的潜在应用价值。

    嵌入式系统开发_USB主机控制器_Arduino兼容开源硬件_基于Mega32U4和MAX3421E芯片的USB设备扩展开发板_支持多种USB外设接入与控制的通用型嵌入式开发平台_.zip

    嵌入式系统开发_USB主机控制器_Arduino兼容开源硬件_基于Mega32U4和MAX3421E芯片的USB设备扩展开发板_支持多种USB外设接入与控制的通用型嵌入式开发平台_

    e2b8a-main.zip

    e2b8a-main.zip

    少儿编程scratch项目源代码文件案例素材-火柴人跑酷(2).zip

    少儿编程scratch项目源代码文件案例素材-火柴人跑酷(2).zip

    【HarmonyOS分布式技术】远程启动子系统详解:跨设备无缝启动与智能协同的应用场景及未来展望

    内容概要:本文详细介绍了HarmonyOS分布式远程启动子系统,该系统作为HarmonyOS的重要组成部分,旨在打破设备间的界限,实现跨设备无缝启动、智能设备选择和数据同步与连续性等功能。通过分布式软总线和分布式数据管理技术,它能够快速、稳定地实现设备间的通信和数据同步,为用户提供便捷的操作体验。文章还探讨了该系统在智能家居、智能办公和教育等领域的应用场景,展示了其在提升效率和用户体验方面的巨大潜力。最后,文章展望了该系统的未来发展,强调其在技术优化和应用场景拓展上的无限可能性。 适合人群:对HarmonyOS及其分布式技术感兴趣的用户、开发者和行业从业者。 使用场景及目标:①理解HarmonyOS分布式远程启动子系统的工作原理和技术细节;②探索该系统在智能家居、智能办公和教育等领域的具体应用场景;③了解该系统为开发者提供的开发优势和实践要点。 其他说明:本文不仅介绍了HarmonyOS分布式远程启动子系统的核心技术和应用场景,还展望了其未来的发展方向。通过阅读本文,用户可以全面了解该系统如何通过技术创新提升设备间的协同能力和用户体验,为智能生活带来新的变革。

    嵌入式八股文面试题库资料知识宝典-C and C++ normal interview_1.zip

    嵌入式八股文面试题库资料知识宝典-C and C++ normal interview_1.zip

    少儿编程scratch项目源代码文件案例素材-激光反弹.zip

    少儿编程scratch项目源代码文件案例素材-激光反弹.zip

    COMSOL相控阵检测技术在有机玻璃斜楔中检测工件内部缺陷的应用研究

    内容概要:本文详细介绍了COMSOL相控阵检测技术在有机玻璃斜楔上放置16阵元进行工件内部缺陷检测的方法。首先阐述了相控阵检测技术的基本原理,特别是通过控制各阵元的激发时间和相位来实现声波的聚焦和扫描。接着,重点解析了横孔缺陷的反射接收波,解释了波的折射现象及其背后的物理原因。最后,通过实例展示了COMSOL模拟声波传播过程的成功应用,验证了该技术的有效性和准确性。 适合人群:从事固体力学、无损检测领域的研究人员和技术人员,尤其是对相控阵检测技术和COMSOL仿真感兴趣的读者。 使用场景及目标:适用于需要精确检测工件内部缺陷的研究和工业应用场景,旨在提高检测精度和效率,确保产品质量和安全。 其他说明:文中提到的声速匹配现象有助于理解波在不同介质间的传播特性,这对优化检测参数设置有重要意义。

Global site tag (gtag.js) - Google Analytics