实验要求
image.png实验代码
区间树的很多操作是红黑树进行一点简单的修改,区间树中加入的max域 注意在插入和旋转的时候进行对max域进行维护与更新。
一点新学到的tricks
多用python的定向输出比较适合需要输出多个文件的时候。
一点问题
对于NIL的指针,处理的还不够巧妙,整个代码基本是算法导论照搬,但是NIL指针的定义和处理还需要修改和理解
代码
#USTC Donglai Ma
# The basic code come from 'Introduction to Algorithms'
import sys
class RBTreenode(object):
def __init__(self,inter):
nil = Inter(-1,-1)
self.parent = None
self.key = inter.low
self.left = None
self.right = None
self.color = "black"
self.max = 0
# Inter for code x
self.inter = inter
# def printnode_inorder(self):
# # In-order traversal
# if self.left:
# self.left.print()
# print(self.key)
# if self.right:
# self.right.print()
#
#
class Inter:
def __init__(self,low,high):
self.low = low
self.high = high
class RBTree:
# Insert,Delete,Print,Left Rotate, Right Rotate
def __init__(self):
# Notice that the nil here use 0 to present
nil = RBTreenode(Inter(-1,-1))
self.nil = nil
self.root = self.nil
# Left Rotate
def left_rotate(T, x):
# Left Rotate
y = x.right
x.right = y.left
if y.left != T.nil:
y.left.parent = x
y.parent = x.parent
if x.parent == T.nil:
T.root = y
elif x == x.parent.left:
x.parent.left = y
else:
x.parent.right = y
y.left = x
x.parent = y
# update the max
y.max = x.max
x.max = max(x.inter.high,x.left.max,x.right.max)
def right_rotate( T, x):
# Right Rotate
y = x.left
x.left = y.right
if y.right != T.nil:
y.right.parent = x
y.parent = x.parent
if x.parent == T.nil:
T.root = y
elif x == x.parent.right:
x.parent.right = y
else:
x.parent.left = y
y.right = x
x.parent = y
# update the max
x.max = y.max
y.max = max(y.right.max,y.left.max,y.inter.high)
def rb_insert(T, z):
# insert the node
y = T.nil
x = T.root
while x != T.nil:
y = x
if z.key < x.key:
x = x.left
else:
x = x.right
z.parent = y
if y == T.nil:
T.root = z
elif z.key < y.key:
y.left = z
else:
y.right = z
z.left = T.nil
z.right = T.nil
z.color = 'red'
# update the max of z
z.max = max(z.inter.high,z.left.max,z.right.max)
rb_insert_fixup(T, z)
# update to root's max
while z.parent!=T.nil:
z.parent.max = max(z.parent.max,z.max)
z=z.parent
def rb_insert_fixup( T, z):
while z.parent.color == 'red':
if z.parent == z.parent.parent.left:
y = z.parent.parent.right
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
z = z.parent
left_rotate(T, z)
z.parent.color = 'black' # case 3
z.parent.parent.color = 'red'
right_rotate(T,z.parent.parent)
else:
y = z.parent.parent.left
if y.color == 'red':
z.parent.color = 'black'
y.color = 'black'
z.parent.parent.color = 'red'
z = z.parent.parent
else:
if z == z.parent.left:
z = z.parent
right_rotate(T, z)
z.parent.color = 'black'
z.parent.parent.color = 'red'
left_rotate(T, z.parent.parent)
T.root.color = 'black'
def rb_transplant(T, u, v):
if u.parent == T.nil:
T.root = v
elif u == u.parent.left:
u.parent.left = v
else:
u.parent.right = v
v.parent = u.parent
def rb_delete(T, m):
# delete the z node
#z = search_tree(T.root,m)
z = interval_search(T,m)
y = z
y_original_color = y.color
if z.left == T.nil:
x = z.right
rb_transplant(T, z, z.right)
elif z.right == T.nil:
x = z.left
rb_transplant(T, z, z.left)
else:
y = tree_minimum(T,z.right)
y_original_color = y.color
x = y.right
if y.parent == z:
x.parent = y
else:
rb_transplant(T, y, y.right)
y.right = z.right
y.right.parent = y
rb_transplant(T, z, y)
y.left = z.left
y.left.parent = y
y.color = z.color
if y_original_color == 'black':
rb_delete_fixup(T, x)
def rb_delete_fixup(T, x):
while x != T.root and x.color == 'black':
if x == x.parent.left:
w = x.parent.right
if w.color == 'red':
w.color = 'black' #case 1
x.parent.color = 'red'
left_rotate(T, x.parent)
w = x.parent.right
if w.left.color == 'black' and w.right.color == 'black':
w.color = 'red' #case 2
x = x.parent
else:
if w.right.color == 'black':
w.left.color = 'black' # case 3
w.color = 'red'
right_rotate(T, w)
w = x.parent.right
w.color = x.parent.color # case 4
x.parent.color = 'black'
w.right.color = 'black'
left_rotate(T, x.parent)
x = T.root
else:
w = x.parent.left
if w.color == 'red':
w.color = 'black'
x.parent.color = 'red'
right_rotate(T, x.parent)
w = x.parent.left
if w.right.color == 'black' and w.left.color == 'black':
w.color = 'red'
x = x.parent
else:
if w.left.color == 'black':
w.right.color = 'black'
w.color = 'red'
left_rotate(T, w)
w = x.parent.left
w.color = x.parent.color
x.parent.color = 'black'
w.left.color = 'black'
right_rotate(T, x.parent)
x = T.root
x.color = 'black'
def tree_minimum(T,x):
while x.left != T.nil:
x = x.left
return x
# def search_tree(A,x):
# while x != A.key:
# if x<A.key:
# A = A.left
# else:
# A = A.right
#
# return A
#Here we need to check the interval,i = interval
def search_tree(A,i):
while i.low !=A.key:
if i.low <A.key:
A = A.left
else:
A = A.right
return A
# Although it's interval , the key is interval.low and
# I assume key is same which means the i must in the Tree
def interval_search(T,interval):
x = T.root
#not overlap
while x!= T.nil and(x.inter.low >interval.high or x.inter.high<interval.low):
if x.left!=T.nil and x.left.max>=interval.low:
x=x.left
else:
x=x.right
return x
def Insort(x):
if x!= None:
Insort(x.left)
if x.key!=0:
print('key:', x.key,'x.parent',x.parent.key)
Insort(x.right)
#def preorder_sort(x):
# if x!=None:
# if x.key!=0:print(x.key)
# preorder_sort(x.left)
# preorder_sort(x.right)
def inorder_sort(x):
if x!= None:
inorder_sort(x.left)
if x.key!=-1:
print(x.inter.low,x.inter.high,x.max)
inorder_sort(x.right)
#def postorder_sort(x):
# if x!= None:
# postorder_sort(x.left)
# postorder_sort(x.right)
# if x.key!=0:print(x.key)
# Generate the inputB
import numpy as np
import random
import time
# list = []
# list_left = [x for x in range(0,25)]
# for i in range (30,50):
# list_left.append(i)
# random.shuffle(list_left)
# print(list_left)
# list = []
#
#
# for i in range(len(list_left)):
# if list_left[i]<25:
# list.append((list_left[i],random.randint(list_left[i]+1,25)))
# else:
# list.append((list_left[i],random.randint(list_left[i]+1,50)))
# print(list)
#
#
# np.savetxt("../inputB/random_interval_file.txt",list,fmt="%d")
# read the input
list_all= np.loadtxt("../inputB/random_interval_file.txt",dtype='int')
#print(list_all[1,1])
list_inter = []
for i in range(len(list_all)):
m = Inter(list_all[i,0],list_all[i,1])
list_inter.append(m)
T = RBTree()
for i in range(0,30):
rb_insert(T,RBTreenode(list_inter[i]))
filename_inorder = str('../outputB/inorder.txt')
filename_delete_data = str('../outputB/delete_data.txt')
filename_search = str('../outputB/search.txt')
savedStdout = sys.stdout #保存标准输出流
with open(filename_inorder, 'w+') as file:
sys.stdout = file
inorder_sort(T.root)
file.close()
with open(filename_delete_data, 'w+') as file:
sys.stdout = file
list_delete = random.sample(list_inter,3)
rb_delete(T,list_delete[0])
rb_delete(T,list_delete[1])
rb_delete(T,list_delete[2])
print('The deleted node is')
for i in range(3):
print(list_delete[i].low,list_delete[i].high,'\n')
print ('The final inorder is ')
inorder_sort(T.root)
file.close()
with open(filename_search, 'w+') as file:
sys.stdout = file
a = Inter(3,11)
b = Inter(26,27)
c = Inter(33,45)
print('Search (3,11)')
print(interval_search(T,a).inter.low,interval_search(T,a).inter.high)
print('Search (26,27)')
print(interval_search(T,b).inter.low,interval_search(T,b).inter.high)
print('Search (33,45)')
print(interval_search(T,c).inter.low,interval_search(T,c).inter.high)
file.close()
sys.stdout = savedStdout #恢复标准输出流
网友评论