红黑树是上一章二叉搜索树的改进,实现一种平衡 ,保证不会出现二叉树变链表的情况,基本动态集合操作的时间复杂度为O(lgn)

实际用途:c++stl中的set,map是用他实现的

红黑树的性质:

1.每个结点或是红色的,或是黑色的

2.跟结点是黑色的

3.每个叶结点(NIL)是黑色

4.如果一个结点是红色的,则它的两个结点都是黑色的

5.对每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同的数目的黑色结点(数目被称为黑高bh(x))

如下图:

(T.nil 哨兵后面被忽略 None)

红黑树是二叉搜索树的改进,为了保证树的相对平衡,主要的不同就是增加了颜色这一属性,而后以颜色为起点的5条性质,为实现这5条性质我们要旋转和改色(插入,删除时)。

结点代码:

class Node: #红黑树结点类

    def __init__(self,data):
self.left = None
self.right = None
self.parent = None
self.data = data
self.color = 'red' #初始化为red不是black看第5条黑高变化不好调节而red要好些

红黑树的旋转:保证平衡的一个关键

通过旋转在插入/删除时保持红黑树的5条性质-》保持树的相对平衡

这是基本的转换过程

主要调节 x和β ( β代码用B代替) x.parent和y  x和y之间的关系

代码过程:

   def left_rotate(self,root):
'''
围绕self转
root根结点 '''
x = self
#y必须存在
y = x.right
if y == None:
return ;
B = y.left
#x 和 B
x.right = B
if B != None:
B.parent = x #y和x.parent
y.parent = x.parent
if x.parent == None:
#x为root结点
root = y
elif x == x.parent.left:
x.parent.left = y
else:
x.parent.right = y #x和y
y.left = x
x.parent = y def right_rotate(self,root):
'''
围绕self转
root根结点 '''
y = self
#x必须存在
x = y.left
if x == None:
return ;
B = x.right
#y 和 B
y.left = B
if B != None:
B.parent = y #x和y.parent
x.parent = y.parent
if y.parent == None:
#y为root结点
root = x
elif y == y.parent.left:
y.parent.left = x
else:
y.parent.right = x #x和y
x.right = y
y.parent = x

红黑树插入:

我想先写一下我们插入的前提:

1.我们要保证红黑树的5点性质(将使用旋转变色保持-->保证达到先对平衡的关键)

2.我们默认插入的是红点--(破坏第2,4)对比插入黑点(破坏5)黑高的变化要求的是每个结点 更难满足

3.我们插入的位置都在叶子结点的位置(可以回忆一下二叉搜索树的代码)

插入的前一部分代码:(在二叉搜索树上的修改)

 def tree_insert(self,data):
#插入data
node = self
while node:
if data < node.data:
next = node.left
else:
next = node.right
if next:
node = next
else:
break
nn = self.createNode(data) #nn初始化颜色为red
if data < node.data: #注data为根节点 不能不使用这个函数
node.left = nn
node.left.parent = node
else:
node.right = nn
node.right.parent = node #我没有使用哨兵
#变化
nn.re_insert_fixup(self)#旋转变色保持性质
return nn

画出所有的可能:#带有z的为插入位置

if 没有父亲结点(是root): #在RBTree中直接改成黑色

graph graphname{ //图
z
z[color = red,style = filled]; //图中点的属性
}

 

昨天:找了一个用dit语言画图的一款软件GVEdit(360软件管家里有,官网好像被墙了??使用边学习边使用)我参考的网址:http://blog.csdn.net/zhangskd/article/details/8250470

elif 有父亲结点:

    if 父亲结点为黑色:

graph graphname{
7--5--z;//z我们插入的点
5--NULL[color = white]; //我使用了NULL写为白色伪装了一下,使图看起来更像二叉树 暂定的解决方法
7--8;
7,z[color = red,style = filled];
5,8[color = gray,style = filled,fontcolor = white];//使用灰色代替黑色 黑色显示太重
NULL[color = white,fontcolor=white]
}

     显然父亲结点为为黑对树的五个性质没有影响{注:关于第3条我默认是省略了叶子结点叶子结点是黑色}

    elif 父亲结点为红色://到这才开始书上的伪代码

            if 父亲在祖父的左边

                   if 叔父为红色:#8为红色 书上情况1 #这里省略了一般部分 叔父就在右边下面的8

         #省去dot代码篇幅太长不好复习,也只是在上面的代码改的就不再谈了   

          看到这我老是在想可不可能转一下,但是根据4是不可能的,所以我们的选择是换色

        显然黑高没变,如果7结点是root 直接改成黑色,如果不是应该递归处理//7变色了所以要处理一下

              if 结点 z->p->p == root

                    把其变黑

               else

  z = z->p->p#z在这里上移了 因为上面的7变色了

                    重新开始

         elif 叔父为黑色:

                if z 在父亲的右边: case2

-----变化为---->

                        #z是表示我们在代码中要变化的位置 #这图画的不好    偷懒了- -、

                        #显然情况变成了case3

                        #为什么要么换??没想清

                elif z在父亲的左边: case3

----变为--->

                        显然现在符合条

else:z的父亲在祖父的左边:对称的情况

画了怎么多思路还是有点乱我将条件判断拿出来,从整体上看一下。#和书上的代码可能不同 他省略了很多

if 没有父亲结点(是root):

elif 有父亲结点:

    if 父亲结点为黑色:

    elif 父亲结点为红色:

    if 父亲在祖父的左边 #如果是红必有父结点

        if 叔父为红色:#case1

            #z在父亲的左边和右边都没有变化

            if 结点 z->p->p == root:

            else: 递归重新处理

        elif 叔父为黑色:情况2 + 3

            if z在父亲的右边:case2

            elif z在父亲的左边:case3

    elif 父亲在祖父的左边

   

  def re_insert_fixup(self,root):
#插入时调节平衡部分
z = self while z.parent != None and z.parent.color == 'red': #如果有父亲结点且他为红色
if z.parent == z.parent.parent.left:
y = z.parent.parent.right #y是z的叔父
if y.color == 'red': #case 1
z.parent.color = 'black'
y.color = 'black'
z.parent.parent.color = 'red'
z = z.parent.parent
else:
if z == z.parent.right: #case 2 --->case3
z = z.parent
z.right_rotate(root)
z.parent.color = 'black'
z.parent.parent.color = 'red'
z.parent.parent.right_rotate(root)
else:
y = z.parent.parent.left #y是z的叔父
if y.color == 'red': #case 1
z.parent.color = 'black'
y.color = 'black'
z.parent.parent = 'red'
z = z.parent.parent
else:
if z == z.parent.left: #case 2 --->case3
z = z.parent
z.left_rotate(root)
z.parent.color = 'black'
z.parent.parent.color = 'red'
z.parent.parent.left_rotate(root) root.color = 'black'

参考引用:

http://blog.csdn.net/fxjtoday/article/details/6448083

http://www.wutianqi.com/?p=2449

http://blog.csdn.net/zhangskd/article/details/8250470

算法导论 第十三章 红黑树(python)-1插入的更多相关文章

  1. 算法导论 第六章 堆排序(python)

    6.1堆 卫星数据:一个带排序的的数通常是有一个称为记录的数据集组成的,每一个记录有一个关键字key,记录的其他数据称为卫星数据. 原地排序:在排序输入数组时,只有常数个元素被存放到数组以外的空间中去 ...

  2. 算法导论 第七章 快速排序(python)

    用的最多的排序 平均性能:O(nlogn){随机化nlogn} 原地址排序 稳定性:不稳定 思想:分治 (切分左右) 学习方式:自己在纸上走一遍   def PARTITION(A,p,r): x = ...

  3. 红黑树Python实现

    # coding=utf-8 # 红黑树Python实现 # 颜色常量 RED = 0 BLACK = 1 def left_rotate(tree, node): if not node.right ...

  4. 第十四章 红黑树——C++代码实现

    红黑树的介绍 红黑树(Red-Black Tree,简称R-B Tree),它一种特殊的二叉查找树.红黑树是特殊的二叉查找树,意味着它满足二叉查找树的特征:任意一个节点所包含的键值,大于等于左孩子的键 ...

  5. 数据结构和算法(Golang实现)(29)查找算法-2-3树和左倾红黑树

    某些教程不区分普通红黑树和左倾红黑树的区别,直接将左倾红黑树拿来教学,并且称其为红黑树,因为左倾红黑树与普通的红黑树相比,实现起来较为简单,容易教学.在这里,我们区分开左倾红黑树和普通红黑树. 红黑树 ...

  6. 数据结构与算法--从平衡二叉树(AVL)到红黑树

    数据结构与算法--从平衡二叉树(AVL)到红黑树 上节学习了二叉查找树.算法的性能取决于树的形状,而树的形状取决于插入键的顺序.在最好的情况下,n个结点的树是完全平衡的,如下图"最好情况&q ...

  7. 《算法导论》第二章demo代码实现(Java版)

    <算法导论>第二章demo代码实现(Java版) 前言 表示晚上心里有些不宁静,所以就写一篇博客,来缓缓.囧 拜读<算法导论>这样的神作,当然要做一些练习啦.除了练习题与思考题 ...

  8. 【算法】通过TreeMap理解红黑树

    本文以Java TreeMap为例,从源代码层面,结合详细的图解,剥茧抽丝地讲解红黑树(Red-Black tree)的插入,删除以及由此产生的调整过程. 总体介绍 Java TreeMap实现了So ...

  9. 红黑树-Python实现

    #coding:utf8 #author:HaxtraZ #description:红黑树,python实现 RED = 'red' BLACK = 'black' class RBT: def __ ...

随机推荐

  1. iOS 更改通知栏为白色

    1.在 info.plist 中添加View controller-based status bar appearance,值为NO. 2.在设置状态栏的地方添加代码: UIApplication.s ...

  2. Jquery | 基础 | 慕课网 | (*选择器)

    原生JS var elements1 = document.getElementsByTagName('*'); JQ var elements2 = $("*"); <!D ...

  3. 如何用Python在10分钟内建立一个预测模型

    转载自:https://baijia.baidu.com/s?old_id=307995 最近,我从孙子(指<孙子兵法>——译者注)那里学到了一些策略:速度和准备 “兵之情主速,乘人之不及 ...

  4. Educational Codeforces Round 46 (Rated for Div. 2) E. We Need More Bosses

    Bryce1010模板 http://codeforces.com/contest/1000/problem/E 题意: 给一个无向图,求图的最长直径. 思路:对无向图缩点以后,求图的最长直径 #in ...

  5. Helvetic Coding Contest 2017 online mirror (teams allowed, unrated) J

    Description Heidi's friend Jenny is asking Heidi to deliver an important letter to one of their comm ...

  6. 从一个n位数中选出m位按顺序组成新数并使其最大 || Erasing and Winning UVA - 11491

    就是从n位数中取出n-d个数字按顺序排成一排组成一个新数使得其最大 算法: 从前往后确定每一位.找第i位时,要求后面留下d-i位的空间, 因此第i位应该从第i-1位原来位置+1到第d+i位寻找 用线段 ...

  7. springMVC的架构与执行流程

    SpringMVC术语 前端控制器(DispatcherServlet):接收请求,响应结果,相当于电脑的CPU. 处理器映射器(HandlerMapping):根据URL去查找处理器 处理器(Han ...

  8. c#学习系列之关键字where

    where 子句用于指定类型约束,这些约束可以作为泛型声明中定义的类型参数的变量.    1.接口约束.         例如,可以声明一个泛型类 MyGenericClass,这样,类型参数 T 就 ...

  9. 用IARIdePm新建STM8工程步骤

    IARdePm 如何新建工程及其调用库函数1.新建文件夹,例如,新建文件夹名字(不能为中文)为:Lib_test_GPIO_OUT2.新建工程,Create New Project...,选择Empt ...

  10. css 尺寸、边框、内边距、背景以及css Sprite

    上节课回顾: HTML标签: 格式排版 p 段落 双br 换行 单hr 分隔线 单h1~h6 标题 双pre 原样格式化输出 双div 标签,无任何特殊意义 HTML标签 :文本 <em> ...