很难想象有这么一天我能写出这么抽象的代码。
一般我是将这类代码归结为脑残一类,但是由于是我自己码的,所以暂以青涩称呼 : )。
好消息是根据红黑树插入和删除的每种情况分别写了不同的代码并打上了详细的注释(并不),以后忘了的时候方便复习。
言归正传,为了方便调试,我用pyside2给红黑树写了一个简单的显示界面:
viewer.png
界面的代码如下(也很青涩):
from PySide2 import QtCore, QtGui, QtWidgets
import sys
import RBtree
def fillTree(tree:RBtree.RBTree):
tree.insert(40)
tree.insert(30)
tree.insert(2)
tree.insert(10)
tree.insert(60)
tree.insert(55)
tree.insert(51)
tree.insert(48)
tree.delete(60)
pass
class RBNode(QtWidgets.QGraphicsItem):
def __init__(self, value, color, parent= None):
super(RBNode, self).__init__()
self.item = QtCore.QRectF(0, 0, 40, 40)
self.value = str(value)
self.parent = parent
#print(value)
self.color = QtGui.QColor(255, 0, 0) if color else QtGui.QColor(0, 0, 0)
def boundingRect(self):
return self.item
def paint(self, painter, option, widget = None):
painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
if self.parent:
painter.setPen(QtCore.Qt.blue)
painter.drawLine(QtCore.QPointF(20, 20), self.mapFromScene(self.parent.scenePos()+ QtCore.QPointF(20, 20)) )
painter.setBrush(self.color)
painter.drawEllipse(self.item)
painter.setPen(QtCore.Qt.white)
painter.drawText(QtCore.QRectF(10, 10, 50, 50), self.value)
class RBScene(QtWidgets.QGraphicsScene):
def __init__(self):
super(RBScene, self).__init__()
self.tree = RBtree.RBTree(50)
fillTree(self.tree)
self.fillScene()
def fillScene(self):
rbnode = self.tree.base.left
node = RBNode(rbnode.value, rbnode.color)
self.addItem(node)
self.circle(rbnode.left, node, False, 1.0)
self.circle(rbnode.right, node, True, 1.0)
def circle(self, rbNode:RBtree.RBTree, parent:RBNode, dir:bool, k):
if not rbNode:
return
node = RBNode(rbNode.value, rbNode.color, parent)
pos = parent.scenePos()
k = k* 0.5
time = k* 400
if dir:
pos += QtCore.QPointF(time, time)
else:
pos += QtCore.QPointF(-time, time)
node.setPos(pos)
self.addItem(node)
self.circle( rbNode.left, node, False, k)
self.circle( rbNode.right, node, True, k)
def addNode(self, rbNode, pos):
node = RBNode(rbNode.value, rbNode.color)
node.setPos(pos)
self.addItem(node)
return node
class RBView(QtWidgets.QGraphicsView):
def __init__(self):
super(RBView, self).__init__()
self.setScene(RBScene())
class RBWindow(QtWidgets.QMainWindow):
def __init__(self):
super(RBWindow, self).__init__()
self.view = RBView()
self.setCentralWidget(self.view)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = RBWindow()
window.setGeometry(500, 300, 1200, 1200)
window.show()
sys.exit(app.exec_())
RB-Tree:
class Node():
def __init__(self, value):
self.color = False # False: Black, #True: Black
self.value = value
self.parent = None
self.lr = False # False: left, True: right
self.left = None
self.right = None
class RBTree():
def __init__(self, rootValue):
self.base = Node(-1)
self.root = Node(rootValue)
self.root.parent = self.base
self.root.lr = False
self.base.left = self.root
self.count = 1
def findNode(self, value):
node = self.base.left
while True:
if value == node.value:
return node
elif value > node.value:
if node.right:
node = node.right
else:
return False
else:
if node.left:
node = node.left
else:
return False
def leftRot(self, newNode, parent, grand):
brother = parent.right
parent.parent = grand.parent
parent.right = grand
parent.lr = grand.lr
if grand.lr:
grand.parent.right = parent
else:
grand.parent.left = parent
parent.color = False
grand.parent = parent
grand.left = brother
grand.color = True
grand.lr = True
if brother:
brother.parent = grand
def rightRot(self, newNode, parent, grand):
brother = parent.left
parent.parent = grand.parent
parent.left = grand
parent.color = False
parent.lr = grand.lr
if grand.lr:
grand.parent.right = parent
else:
grand.parent.left = parent
grand.right = brother
grand.parent = parent
grand.color = True
grand.lr = False
if brother:
brother.parent = grand
def insert(self, value):
#part 1 find pos and insert
node = self.base.left
newNode = Node(value)
newNode.color = True
while True:
if value > node.value:
if node.right:
node = node.right
else:
node.right = newNode
newNode.parent = node
newNode.lr = True
break
else:
if node.left:
node = node.left
else:
node.left = newNode
newNode.parent = node
newNode.lr = False
break
#part2 resort
while True:
# parent is black
parent = newNode.parent
if not parent.color:
break
uncle = None
uncleColor = False
grand = parent.parent
parentLR = parent.lr
if grand:
uncle = grand.left if parentLR else grand.right
if uncle:
uncleColor = uncle.color
# parent is red, uncle is black or None
if not uncleColor:
#parent on left
if not parentLR:
#new node on left
if not newNode.lr:
self.leftRot( newNode, parent, grand)
#new node on right
else:
newNode.left = parent
newNode.parent = grand
newNode.lr = False
parent.right = None
parent.parent = newNode
parent.lr = False
grand.left = newNode
self.leftRot( parent, newNode, grand)
#parent on right
else:
#new node on left
if not newNode.lr:
newNode.parent = grand
newNode.right = parent
newNode.lr = True
parent.left = None
parent.parent = newNode
parent.lr = True
grand.right = newNode
self.rightRot(parent, newNode, grand)
#new node on right
else:
self.rightRot(newNode, parent, grand)
break
# parent is red, uncle is red
else:
if uncle:
uncle.color = False
parent.color = False
# if is root, break
if self.base.left == grand:
grand.color = False
break
#else: loop
grand.color = True
newNode = grand
def nullNode(self, node):
node.parent = None
Node.left = None
Node.right = None
def delete(self, value):
delNode = self.findNode(value)
if not delNode: return False
parent = delNode.parent
grand = parent.parent
brother = parent.left if delNode.lr else parent.right
lchild = delNode.left
rchild = delNode.right
# left loop search single branch node or zero branch node
while lchild and rchild:
delNode.value = lchild.value
delNode = lchild
parent = delNode.parent
grand = parent.parent
brother = parent.left if delNode.lr else parent.right
lchild = delNode.left
rchild = delNode.right
# if delnode is red
# just del node
if delNode.color:
if delNode.lr:
parent.right = None
else:
parent.left = None
self.nullNode(delNode)
return True
# del Node is black
if lchild or rchild:
#child must be red
if lchild:
if delNode.lr:
parent.right = lchild
else:
parent.left= lchild
lchild.parent = parent
lchild.lr = delNode.lr
lchild.color = False
else:
if delNode.lr:
parent.right = rchild
else:
parent.left= rchild
rchild.parent = parent
rchild.lr = delNode.lr
rchild.color = False
self.nullNode(delNode)
return True
# no child
# if brother is red
# brother must have two black child
#step 1: del frist
brother = parent.left if delNode.lr else parent.right
if delNode.lr:
parent.right = None
else:
parent.left = None
self.nullNode(delNode)
while True:
blNode = brother.left
brNode = brother.right
if brother.color:
#step 2: resort
# parent left rot
brother.color = False
brother.parent = parent.parent
brother.lr = parent.lr
parent.color = True
parent.parent = brother
if delNode.lr:
brother.right = parent
parent.left = brNode
parent.right = None
parent.lr = True
else:
brother.left = parent
parent.right = blNode
parent.left = None
parent.lr = False
return True
# brother is black
# brother child is all null : error
# brother child have |1 red |
# if bl is red
if blNode:
# step 1: brother right rot
# step 2: parent left rot
if brother.lr:
parent.right = blNode
blNode.parent = parent
blNode.lr = brother.lr
blNode.right = brother
brother.parent = blNode
brother.left = None
blNode.parent = parent.parent
blNode.lr = parent.lr
blNode.color = parent.color
blNode.left = parent
if parent.lr:
parent.parent.right = blNode
else:
parent.parent.left = blNode
parent.parent = blNode
parent.lr = False
parent.color = False
parent.right = None
else:
# parent right rot
brother.parent = parent.parent
brother.right = parent
brother.lr = parent.lr
brother.color = parent.color
if parent.lr:
parent.parent.right = brother
else:
parent.parent.left = brother
parent.lr = True
parent.color = False
parent.parent = brother
parent.left = brNode
blNode.color = False
return True
# if bl is red
if brNode:
if brother.lr:
brother.parent = parent.parent
brother.lr = parent.lr
brother.left = parent
brother.color = parent.color
if parent.lr:
parent.parent.right = brother
else:
parent.parent.left = brother
parent.parent = brother
parent.lr = False
parent.color = False
parent.right = blNode
brNode.color = False
else:
brNode.parent = parent
brNode.right = brother
brNode.lr = brother.lr
parent.left = brNode
brother.parent = brNode
brother.lr = True
brother.left = None
brNode.lr = parent.lr
brNode.color = parent.color
brNode.right = parent
brNode.parent = parent.parent
if parent.lr:
parent.parent.right = brNode
else:
parent.parent.left = brNode
parent.parent = brNode
parent.lr = True
parent.color = False
parent.right = None
return True
#if brother have no child
# parent is red
if parent.color:
parent.color = False
brother.color = True
return True
# parent and brother is black
brother.color = True
delNode = parent
parent = parent.parent
brother = parent.left if delNode.lr else parent.right