算法导论之红黑树&区间树

实验要求

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 xinterval.high or x.inter.high=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 #恢复标准输出流



你可能感兴趣的:(算法导论之红黑树&区间树)