您的位置:首页 > 理论基础 > 数据结构算法

[从头学数学] 第261节 Python实现数据结构:红黑树(RB Tree)

2016-09-09 11:27 573 查看
剧情提要:
阿伟看到了一本比较有趣的书,是关于《计算几何》的,2008年由北清派出版。很好奇
它里面讲了些什么,就来看看啦。

正剧开始:

星历2016年09月09日 11:26:00, 银河系厄尔斯星球中华帝国江南行省。

[工程师阿伟]正在和[机器小伟]一起研究[计算几何]]。





<span style="font-size:18px;">#
from random import randint

RED = 'R'
BLACK = 'B'

###
# @usage 红黑树
# @author mw
# @date 2016年09月09日 星期五 11:24:48
# @param
# @return
#
###
class RBTree():
class __RBTreeNode():
'''红黑树的节点类型'''
def __init__(self, val):
self.val = val
self.left = None
self.right = None
self.parent = None
self.color = '*';

def paint(self, color):
self.color = color

def __iter__(self):
if self.left != None:
for elem in self.left:
yield elem

if (self.val != None):
yield self.val

if self.right != None:
for elem in self.right:
yield elem

#迭代的是Node类型,用于删除结点
def iternodes(self):
if self.left != None:
for elem in self.left.iternodes():
yield elem

if self != None and self.val != None:
yield self

if self.right != None:
for elem in self.right.iternodes():
yield elem

def info(self):
s = 'Key='+str(self.val)+', '+\
'LChild='+str(self.left)+', '+\
'RChild='+str(self.right)+', '+\
'parent='+str(self.parent)+', '+\
'Color='+str(self.color);

print(s);

def __str__(self):
return str(self.val);

def __repr__(self):
if self != None:
s_1 = str(self.val);
else:
s_1 = 'None';

if self.left != None:
s_2 = str(self.left.val);
else:
s_2 = 'None';

if self.right != None:
s_3 = str(self.right.val);
else:
s_3 = 'None';

s_4 = str(self.parent);
s_5 = str(self.color);

return '__RBTreeNode('+s_1+', ' + s_2 +', ' + s_3 +', '+ s_4 +', '+s_5+')';

def __init__(self):
# self.items = []
self.root = None
self.zlist = []

def LRotate(self, x):
# x是一个RBTree.__RBTreeNode
y = x.right
if y is None:
# 右节点为空,不旋转
pass;
else:
beta = y.left
x.right = beta
if beta is not None:
beta.parent = x

p = x.parent
y.parent = p
if p is None:
# x原来是root
self.root = y
elif x == p.left:
p.left = y
else:
p.right = y
y.left = x
x.parent = y

def RRotate(self, y):
# y是一个节点
x = y.left
if x is None:
# 左节点为空,不旋转
pass;
else:
beta = x.right
y.left = beta
if beta is not None:
beta.parent = y

p = y.parent
x.parent = p
if p is None:
# y原来是root
self.root = x
elif y == p.left:
p.left = x
else:
p.right = x
x.right = y
y.parent = x

#插入
def insert(self, val):
z = RBTree.__RBTreeNode(val)
y = None
x = self.root
while x is not None:
y = x
if z.val < x.val:
x = x.left
else:
x = x.right

z.paint(RED)
z.parent = y

if y is None:
# 插入z之前为空的RBTree
self.root = z
self.insert_Fixup(z)
return

if z.val < y.val:
y.left = z
else:
y.right = z

if y.color == RED:
# z的父节点y为红色,需要fixup。
# 如果z的父节点y为黑色,则不用调整
self.insert_Fixup(z)

else:
return

def insert_Fixup(self, z):
# case 1:z为root节点
if z.parent is None:
z.paint(BLACK)
self.root = z
return

# case 2:z的父节点为黑色
if z.parent.color == BLACK:
# 包括了z处于第二层的情况
# 这里感觉不必要啊。。似乎z.parent为黑色则不会进入fixup阶段
return

# 下面的几种情况,都是z.parent.color == RED:
# 节点y为z的uncle
p = z.parent
g = p.parent # g为x的grandpa
if g is None:
return
# return 这里不能return的。。。
if g.right == p:
y = g.left
else:
y = g.right

# case 3-0:z没有叔叔。即:y为NIL节点
# 注意,此时z的父节点一定是RED
if y == None:
if z == p.right and p == p.parent.left:
# 3-0-0:z为右儿子,且p为左儿子,则把p左旋
# 转化为3-0-1或3-0-2的情况
self.LRotate(p)
p, z = z, p
g = p.parent
elif z == p.left and p == p.parent.right:
self.RRotate(p)
p, z = z, p

g.paint(RED)
p.paint(BLACK)
if p == g.left:
# 3-0-1:p为g的左儿子
self.RRotate(g)
else:
# 3-0-2:p为g的右儿子
self.LRotate(g)

return

# case 3-1:z有黑叔
elif y.color == BLACK:
if p.right == z and p.parent.left == p:
# 3-1-0:z为右儿子,且p为左儿子,则左旋p
# 转化为3-1-1或3-1-2
self.LRotate(p)
p, z = z, p
elif p.left == z and p.parent.right == p:
self.RRotate(p)
p, z = z, p

p = z.parent
g = p.parent

p.paint(BLACK)
g.paint(RED)
if p == g.left:
# 3-1-1:p为g的左儿子,则右旋g
self.RRotate(g)
else:
# 3-1-2:p为g的右儿子,则左旋g
self.LRotate(g)

return

# case 3-2:z有红叔
# 则涂黑父和叔,涂红爷,g作为新的z,递归调用
else:
y.paint(BLACK)
p.paint(BLACK)
g.paint(RED)
new_z = g
self.insert_Fixup(new_z)

#删除
def delete(self, val):
curNode = self.root
while curNode is not None:
if val < curNode.val:
curNode = curNode.left
elif val > curNode.val:
curNode = curNode.right
else:
# 找到了值为val的元素,正式开始删除
if curNode.left is None and curNode.right is None:
# case1:curNode为叶子节点:直接删除即可
if curNode == self.root:
self.root = None
else:
p = curNode.parent
if curNode == p.left:
p.left = None
else:
p.right = None

elif curNode.left is not None and curNode.right is not None:
sucNode = self.SUCCESOR(curNode)
curNode.val, sucNode.val = sucNode.val, curNode.val
self.delete(sucNode.val)

else:
p = curNode.parent
if curNode.left is None:
x = curNode.right
else:
x = curNode.left
if curNode == p.left:
p.left = x
else:
p.right = x
x.parent = p
if curNode.color == BLACK:
self.delete_Fixup(x)
curNode = None
return False

def delete_Fixup(self, x):
p = x.parent
# w:x的兄弟结点
if x == p.left:
w = x.right
else:
w = x.left

# case1:x的兄弟w是红色的
if w.color == RED:
p.paint(RED)
w.paint(BLACK)
if w == p.right:
self.LRotate(p)
else:
self.RRotate(p)

if w.color == BLACK:
# case2:x的兄弟w是黑色的,而且w的两个孩子都是黑色的
if w.left.color == BLACK and w.right.color == BLACK:
w.paint(RED)
if p.color == BLACK:
return
else:
p.color = BLACK
self.delete_Fixup(p)

# case3:x的兄弟w是黑色的,而且w的左儿子是红色的,右儿子是黑色的
if w.left.color == RED and w.color == BLACK:
w.left.paint(BLACK)
w.paint(RED)
self.RRotate(w)

# case4:x的兄弟w是黑色的,而且w的右儿子是红
if w.right.color == RED:
p.paint(BLACK)
w.paint(RED)
if w == p.right:
self.LRotate(p)
else:
self.RRotate(p)

#红黑树信息查询
def info(self):
a = [];
for x in self:
a.append(x);

print(a);

def __iter__(self):
if self.root != None:
return self.root.__iter__()
else:
return [].__iter__()

#传回结点的原始信息
def iternodes(self):
if self.root != None:
return self.root.iternodes()
else:
return [None];

#查找,返回的是结点
def find(self, key):
def _find(key, node):
if node is None:
return None
elif key < node.val:
return _find(key, node.left)
elif key > node.val:
return _find(key, node.right)
else:
return node

if self.root is None:
return None
else:
return _find(key, self.root)

#找最小元素
def findMin(self):
def _findMin(node):
if node.left:
return _findMin(node.left)
else:
return node

if self.root is None:
return None
else:
return _findMin(self.root)

#找最大元素
def findMax(self):
def _findMax(node):
if node.right:
return _findMax(node.right)
else:
return node

if self.root is None:
return None
else:
return _findMax(self.root)

#求结点高度
def height(self, node):
if (node == None):
return 0;
else:
m = self.height(node.left);
n = self.height(node.right);
return max(m, n)+1;

#寻找节点路径
def findNodePath(self, root, node):
path = [];
if root == None or root.val == None:
path = [];
return path

while (root != node):
if node.val < root.val:
path.append(root);
root = root.left;
elif node.val >= root.val:
path.append(root);
root = root.right;
else:
break;

path.append(root);
return path;

#寻找父结点
def parent(self, root, node):
path = self.findNodePath(root, node);
if (len(path)>1):
return path[-2];
else:
return None;

#求某元素是在树的第几层
#约定根为0层
#这个计算和求结点的Height是不一样的
def level(self, elem):
if self.root != None:
node = self.root;
lev = 0;

while (node != None):
if elem < node.val:
node = node.left;
lev+=1;
elif elem > node.val:
node = node.right;
lev+=1;
else:
return lev;

return -1;

else:
return -1;

def __len__(self):
a = [];
for x in self:
a.append(x);

return len(a);

def __contains__(self, val):
if self.find(val) != None:
return True;

return False;
#</span>

用例:
<span style="font-size:18px;">#
if __name__ == '__main__':
rbt=RBTree()
b = []
N = 10;

data = [0, 24, 26, 79, 93, 99, 335, 378, 440, 494];

data2 = [90, 115, 168, 236, 270, 271, 300, 393, 465, 489];

#生成随机原始数据
for i in range(N):
m = randint(0, 500)
rbt.insert(m)
b.append(m)

#插入
for x in data2:
rbt.insert(x);

for node in rbt.iternodes():
node.info();

print('root:');
rbt.root.info();

#删除
rbt.delete(236);
rbt.delete(233);
print('root:');
rbt.root.info();
print(len(rbt));

#查找
p = rbt.find(168);
if (p != None):
p.info();

#
print('max:');
rbt.findMax().info();
print('min:');
rbt.findMin().info();
print('height:', rbt.height(rbt.root));
print(168 in rbt);
print(1002 in rbt);

#
for x in rbt.iternodes():
print(rbt.findNodePath(rbt.root, x));
print(rbt.level(x.val));

>>>
Key=33, LChild=None, RChild=None, parent=90, Color=R
Key=90, LChild=33, RChild=115, parent=141, Color=B
Key=115, LChild=None, RChild=None, parent=90, Color=R
Key=141, LChild=90, RChild=191, parent=205, Color=R
Key=168, LChild=None, RChild=None, parent=191, Color=R
Key=191, LChild=168, RChild=None, parent=141, Color=B
Key=205, LChild=141, RChild=256, parent=275, Color=B
Key=236, LChild=None, RChild=None, parent=256, Color=B
Key=256, LChild=236, RChild=270, parent=205, Color=R
Key=270, LChild=None, RChild=271, parent=256, Color=B
Key=271, LChild=None, RChild=None, parent=270, Color=R
Key=275, LChild=205, RChild=456, parent=None, Color=B
Key=300, LChild=None, RChild=None, parent=393, Color=R
Key=393, LChild=300, RChild=416, parent=456, Color=B
Key=416, LChild=None, RChild=None, parent=393, Color=R
Key=456, LChild=393, RChild=465, parent=275, Color=B
Key=461, LChild=None, RChild=None, parent=465, Color=B
Key=465, LChild=461, RChild=495, parent=456, Color=R
Key=489, LChild=None, RChild=None, parent=495, Color=R
Key=495, LChild=489, RChild=None, parent=465, Color=B
root:
Key=275, LChild=205, RChild=456, parent=None, Color=B
root:
Key=275, LChild=205, RChild=456, parent=None, Color=B
19
Key=168, LChild=None, RChild=None, parent=191, Color=R
max:
Key=495, LChild=489, RChild=None, parent=465, Color=B
min:
Key=33, LChild=None, RChild=None, parent=90, Color=R
height: 5
True
False
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(205, 141, 256, 275, B), __RBTreeNode(141, 90, 191, 205, R), __RBTreeNode(90, 33, 115, 141, B), __RBTreeNode(33, None, None, 90, R)]
4
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(205, 141, 256, 275, B), __RBTreeNode(141, 90, 191, 205, R), __RBTreeNode(90, 33, 115, 141, B)]
3
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(205, 141, 256, 275, B), __RBTreeNode(141, 90, 191, 205, R), __RBTreeNode(90, 33, 115, 141, B), __RBTreeNode(115, None, None, 90, R)]
4
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(205, 141, 256, 275, B), __RBTreeNode(141, 90, 191, 205, R)]
2
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(205, 141, 256, 275, B), __RBTreeNode(141, 90, 191, 205, R), __RBTreeNode(191, 168, None, 141, B), __RBTreeNode(168, None, None, 191, R)]
4
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(205, 141, 256, 275, B), __RBTreeNode(141, 90, 191, 205, R), __RBTreeNode(191, 168, None, 141, B)]
3
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(205, 141, 256, 275, B)]
1
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(205, 141, 256, 275, B), __RBTreeNode(256, None, 270, 205, R)]
2
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(205, 141, 256, 275, B), __RBTreeNode(256, None, 270, 205, R), __RBTreeNode(270, None, 271, 256, B)]
3
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(205, 141, 256, 275, B), __RBTreeNode(256, None, 270, 205, R), __RBTreeNode(270, None, 271, 256, B), __RBTreeNode(271, None, None, 270, R)]
4
[__RBTreeNode(275, 205, 456, None, B)]
0
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(456, 393, 465, 275, B), __RBTreeNode(393, 300, 416, 456, B), __RBTreeNode(300, None, None, 393, R)]
3
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(456, 393, 465, 275, B), __RBTreeNode(393, 300, 416, 456, B)]
2
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(456, 393, 465, 275, B), __RBTreeNode(393, 300, 416, 456, B), __RBTreeNode(416, None, None, 393, R)]
3
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(456, 393, 465, 275, B)]
1
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(456, 393, 465, 275, B), __RBTreeNode(465, 461, 495, 456, R), __RBTreeNode(461, None, None, 465, B)]
3
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(456, 393, 465, 275, B), __RBTreeNode(465, 461, 495, 456, R)]
2
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(456, 393, 465, 275, B), __RBTreeNode(465, 461, 495, 456, R), __RBTreeNode(495, 489, None, 465, B), __RBTreeNode(489, None, None, 495, R)]
4
[__RBTreeNode(275, 205, 456, None, B), __RBTreeNode(456, 393, 465, 275, B), __RBTreeNode(465, 461, 495, 456, R), __RBTreeNode(495, 489, None, 465, B)]
3
>>>

#</span>

参见http://blog.csdn.net/napo1987/article/details/37928985

参见http://www.cnblogs.com/zjutzz/p/3281319.html

本节到此结束,欲知后事如何,请看下回分解。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: