数据结构 - 红黑树

#!/usr/bin/env python3.3
# -*- coding:utf-8 -*-
# Copyright 2013'''
满足如下红黑性质的二叉查找树:
1)节点是红色或黑色
2)根是黑色
3)所有叶子都是黑色(叶子是NIL节点)
4)每个红色节点的两个子节点都是黑色(从每个叶子到根的所有路径上不能有两个连续的红色节点)
5)从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点
'''class Node:def __init__(self, key):self.key = keyself.left = Noneself.right = Noneself.color = Noneself.parent = Nonedef grand_parent(self):if self.parent is not None:return self.parent.parentdef uncle(self):if self.grand_parent() is not None:if self.parent == self.grand_parent().left:return self.grand_parent().rightelse:return self.grand_parent().leftdef sibling(self):if self.parent is not None:if self.parent.left == self:return self.parent.rightelse:return self.parent.leftdef __str__(self):return str(self.key)class RBTree:def __init__(self):self.root = Nonedef serach(self, key):node = self.rootwhile node is not None:if key == node.key:return nodeelif key < node.key:node = node.leftelse:node = node.rightdef insert(self, key):# 首先标记为红色node = Node(key)node.color = 'RED'if self.root is None:self.root = nodeelse:root = self.rootwhile root is not None:if key < root.key:if root.left is None:root.left = nodenode.parent = rootbreakelse:root = root.left                else:if root.right is None:root.right = nodenode.parent = rootbreakelse:root = root.rightself._insert_fixup(node)def delete(self, key):node = self.search(key)if node is not None:if node.left is not None and node.right is not None:# 把要删除的节点替换为其后继节点successor = node.rightwhile successor.left is not None:successor = successor.left node.key = successor.keynode = successorif node.left is not None:# 要删除的节点没有右儿子,左儿子(红色)node.left.color = 'BLACK'node.left.parent = node.parentif node.parent is not None:if node.parent.left == node:node.parent.left = node.leftelse:node.parent.right = node.leftelse:self.root = node.leftelif node.right is not None:# 要删除的节点没有左儿子,右儿子(红色)node.right.color = 'BLACK'node.right.parent = node.parentif node.parent is not None:if node.parent.left == node:node.parent.left = node.rightelse:node.parent.right = node.rightelse:self.root = node.rightelse:# 要删除的节点为叶子节点if node.color == 'BLACK':self._delete_fixup(node)if node.parent is not None:if node.parent.left == node:node.parent.left = Noneelse:node.parent.right = Noneelse:self.root = Nonedef _insert_fixup(self, node):if node.parent is None:# 1位于树根上node.color = 'BLACK'elif node.parent.color == 'BLACK':# 2父节点P(黑色)passelif node.uncle() is not None and node.uncle().color == 'RED':# 3父节点P(红色),叔父节点U(红色)node.parent.color = 'BLACK'node.uncle().color = 'BLACK'node.grand_parent().color = 'RED'self._insert_fixup(node.grand_parent())else:# 4父节点P(红色),叔父节点U(缺少或黑色)if node.grand_parent().left == node.parent:# 父节点是祖父节点的左儿子if node.parent.right == node:# 当前节点是父节点的右儿子
                    self._rotate_left(node.parent)node = node.leftnode.parent.color = 'BLACK'node.grand_parent().color = 'RED'self._rotate_right(node.grand_parent())else:# 父节点是祖父节点的右儿子if node.parent.left == node:# 当前节点是父节点的左儿子
                    self._rotate_right(node.parent)node = node.rightnode.parent.color = 'BLACK'node.grand_parent().color = 'RED'self._rotate_left(node.grand_parent())def _delete_fixup(self, node):if node.color == 'RED' or node.parent is None:node.color = 'BLACK'else:if node.sibling().color == 'RED':# 兄弟节点(红色),旋转使兄弟节点变为(黑色)node.sibling().color = 'BLACK'node.parent.color = 'RED'if node.parent.left == node:self._rotate_left(node.parent)else:self._rotate_right(node.parent)if (node.sibling().left is None or node.sibling().left.color == 'BLACK') and (node.sibling().right is None or node.sibling().right.color == 'BLACK'):# 兄弟节点(黑色),两个侄子节点(缺少或黑色)node.sibling().color = 'RED'# Token向上传递(该Token下的所有子孙,黑高度缺少一)
                self._delete_fixup(node.parent)else:# 兄弟节点(黑色),至少一个侄子节点(红色)if node.parent.left == node:if node.sibling().right is None or node.sibling().right.color == 'BLACK':# 左侄子节点(红色),右侄子节点(缺少或黑色)node.sibling().left.color = 'BLACK'node.sibling().color = 'RED'self._rotate_right(node.sibling())# 左侄子节点(缺少或黑色),右侄子节点(红色)node.sibling().color = node.parent.colornode.parent.color = 'BLACK'if node.sibling().right is not None:node.sibling().right.color = 'BLACK'self._rotate_left(node.parent)else:if node.sibling().left is None or node.sibling().left.color == 'BLACK':# 左侄子节点(缺少或黑色),右侄子节点(红色)node.sibling().right.color = 'BLACK'node.sibling().color = 'RED'self._rotate_left(node.sibling())# 左侄子节点(红色),右侄子节点(缺少或黑色)node.sibling().color = node.parent.colornode.parent.color = 'BLACK'if node.sibling().left is not None:node.sibling().left.color = 'BLACK'self._rotate_right(node.parent)def _rotate_left(self, node):right = node.rightright_left = right.left# 处理右子的左子节点if right_left is not None:right_left.parent = node# 处理右子节点right.left = noderight.parent = node.parent# 处理父节点if node.parent is not None:if node.parent.left == node:node.parent.left = rightelse:node.parent.right = rightelse:self.root = right# 处理当前节点node.parent = rightnode.right = right_leftdef _rotate_right(self, node):left = node.leftleft_right = left.right# 处理左子的右子节点if left_right is not None:left_right.parent = node# 处理左子节点left.right = nodeleft.parent = node.parent# 处理父节点if node.parent is not None:if node.parent.right == node:node.parent.right = leftelse:node.parent.left = leftelse:self.root = left# 处理当前节点node.parent = leftnode.left = left_rightdef check_rbtree(rbt):if rbt.root is not None:# 是一棵二叉查找树node_list = [rbt.root]while len(node_list) > 0:node = node_list.pop(0)if node.left is not None:if node.key < node.left.key:print('sort_error')breaknode_list.append(node.left)if node.right is not None:if node.key > node.right.key:print('sort_error')breaknode_list.append(node.right)# 根是黑色if rbt.root.color != 'BLACK':print('root_color_error')# 每个红色节点的两个子节点都是黑色node_list = [rbt.root]while len(node_list) > 0:node = node_list.pop(0)if node.left is not None:if node.color == 'RED' and node.left.color == 'RED':print('double_red')breaknode_list.append(node.left)if node.right is not None:if node.color == 'RED' and node.right.color == 'RED':print('double_red')breaknode_list.append(node.right)# 黑高度相等node_list = [rbt.root]leaf_list = []while len(node_list) > 0:node = node_list.pop(0)if node.left is not None:node_list.append(node.left)if node.right is not None:node_list.append(node.right)if node.left is None or node.right is None:leaf_list.append(node)black_depth = 0while len(leaf_list) > 0:node = leaf_list.pop(0)node_depth = 0while node is not None:if node.color == 'BLACK':node_depth += 1node = node.parentif black_depth == 0:black_depth = node_depthelse:if node_depth != black_depth:print('black_depth_error')breakprint('ok')else:print('empty')

 

转载于:https://www.cnblogs.com/lianghuiwen/archive/2013/03/31/2991862.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/400770.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring mvc ajax 400解决

The request sent by the client was syntactically incorrect. ajax发起请求时报400错误。请求代码如下&#xff1a; var reportId($(obj).parent().parent().parent().children(":first").attr("value"));var isChecked$(obj).prop("checked")…

# Vue3 toRef 和 toRefs 函数

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

二分检索函数lower_bound()和upper_bound()

二分检索函数lower_bound()和upper_bound() 一、说明 头文件&#xff1a;<algorithm> 二分检索函数lower_bound()和upper_bound() lower_bound()&#xff1a;找到大于等于某值的第一次出现upper_bound()&#xff1a;找到大于某值的第一次出现必须从小到大排序后才能用 内…

MSP432P401R TI Drivers 库函数学习笔记(五)PWM

目录API (机翻)函数上机实战配置引脚PWM初始化&#xff0c;实现简易呼吸灯的效果实验结果完整代码myPWM.cmyPWM.hmyTask.cmyTask.hmain.cmain.h平台&#xff1a;Code Composer Studio 10.4.0 MSP432P401R SimpleLink™ 微控制器 LaunchPad™ 开发套件 (MSP-EXP432P401R) API …

65个漂亮的WordPress博客主题

原文地址&#xff1a;http://www.goodfav.com/wordpress-blog-themes-3512.html 我收集了一些最好的WordPress博客主题&#xff0c;以帮助新手和高级的博客主&#xff0c;使用WordPress迅速成立一个惊人的博客网站&#xff01; 为核心的博客平台WordPress的启动和使用WordPress…

防火墙配置十大任务之十,构建虚拟防火墙

防火墙配置任务十构建虚拟防火墙任务拓扑图10.11.inside区域的交换机的基本配置&#xff0c;在交换机上开启vlan2&#xff0c;vlan3&#xff0c;vlan4.三个vlan。图10.22.outside区域的Internet基本配置。图10.33.交换机上连接防火墙接口的配置。图10.44.inside区域各个PC的主机…

使用纯 CSS 实现超酷炫的粘性气泡效果

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

利用 squid 反向代理提高网站性能

简介&#xff1a; 本文在介绍 squid 反向代理的工作原理的基础上&#xff0c;指出反向代理技术在提高网站访问速度&#xff0c;增强网站可用性、安全性方面有很好的用途。作者在具体的实验环境下&#xff0c;利用 DNS 轮询和 Squid 反向代理技术&#xff0c;实现了网站的负载均…

MSP432P401R TI Drivers 库函数学习笔记(六)UART 串口

目录API (机翻)上机实战配置初始化和实验实验结果整体代码myUart.cmyUart.hmyTask.cmyTask.hmain.cmain.h平台&#xff1a;Code Composer Studio 10.4.0 MSP432P401R SimpleLink™ 微控制器 LaunchPad™ 开发套件 (MSP-EXP432P401R) API (机翻) 官方UART API 手册 void UA…

Linux 批量杀死进程(详细版本)

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

orapwd创建密码文件

在CMD里输入命令如下&#xff1a;C:\Documents and Settings\Administrator>orapwd Usage: orapwd file<fname> password<password> entries<users> where file - name of password file (mand), password - password for SYS (mand), entries - maximum …

MSP432 库函数实现 PID 电机调角度、调速

目录引脚配置PWM引脚外部中断测量编码器引脚配置代码部分初始化编码器解读Encoder.cEncoder.h测速和控制部分卡尔曼滤波器&#xff0c;用于对所测速度进行滤波kalman.ckalman.h实验效果速度滤波效果控速效果控角效果平台&#xff1a;Code Composer Studio 10.4.0 MSP432P401R …

CSS基本知识点——带你走进CSS的新世界

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

JS 三级联动 下拉列表

<!-- 我的思路&#xff1a; 1.页面加载时便进入后台获得第一级的值&#xff1b; 2.当第一级的值改变时&#xff0c;清空第二级和第三级的值&#xff0c;并加载第二级的值 3.当第二级的值改变时&#xff0c;清空第三级的值&#xff0c;并加载第三级的值 --><table> …

20.网页卷去的距离与偏移量

我们先来看看下面的图&#xff1a; scrollLeft:设置或获取位于给定对象左边界与窗口中目前可见内容的最左端之间的距离 &#xff0c;即左边灰色的内容。 scrollTop:设置或获取位于对象最顶端与窗口中可见内容的最顶端之间的距离 &#xff0c;即上边灰色的内容。 offsetLeft:获取…

【电赛】一阶卡尔曼滤波器 滤波效果良好

目录代码kalman.ckalman.h滤波效果很久以前抄的&#xff0c;忘了是从哪弄的了 我把它改成了这种结构体指针传参的形式&#xff0c;方便在比赛中应用。应用举例见MSP432 PID 电机调角度、调速。 它曾助力笔者获2020年电赛省一等奖。 代码 Q:过程噪声协方差 Q参数调滤波后的曲线…

130. Surrounded Regions

题目&#xff1a; Given a 2D board containing X and O, capture all regions surrounded by X. A region is captured by flipping all Os into Xs in that surrounded region. For example, X X X X X O O X X X O X X O X XAfter running your function, the board should …

计算机是如何启动的?

从打开电源到开始操作&#xff0c;计算机的启动是一个非常复杂的过程。 我一直搞不清楚&#xff0c;这个过程到底是怎么回事&#xff0c;只看见屏幕快速滚动各种提示......这几天&#xff0c;我查了一些资料&#xff0c;试图搞懂它。下面就是我整理的笔记。 零、boot的含义 先问…

hdu 1536(博弈)

传送门&#xff1a;S-Nim 题意&#xff1a;给n个数的集合s&#xff0c; 再给m 组数据&#xff0c;每组表示 k 堆石子&#xff0c;每次可以取的个数只能是集合s中的数量。问先手胜还是输&#xff1f; 分析&#xff1a;sg函数的经典运用&#xff0c;先预处理出所有数量为0~10000的…

写了个 Markdown 命令行小工具,希望能提高园友们发文的效率!

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…