Red black tree sort: Difference between revisions
Content added Content deleted
(Red black tree sort in FreeBASIC) |
(Red black tree sort in Python) |
||
Line 619: | Line 619: | ||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
See [[Red_black_tree_sort/Phix]]. |
See [[Red_black_tree_sort/Phix]]. |
||
=={{header|Python}}== |
|||
This is based on the code of Shivali Bhadaniya [https://favtutor.com/blogs/red-black-tree-python], which I thought was reasonably intelligible. |
|||
<lang python>#!/usr/bin/python |
|||
# Define Node |
|||
class Node(): |
|||
def __init__(self,val): |
|||
self.val = val # Value of Node |
|||
self.parent = None # Parent of Node |
|||
self.left = None # Left Child of Node |
|||
self.right = None # Right Child of Node |
|||
self.color = 1 # Red Node as new node is always inserted as Red Node |
|||
# Define R-B Tree |
|||
class RBTree(): |
|||
def __init__(self): |
|||
self.NULL = Node ( 0 ) |
|||
self.NULL.color = 0 |
|||
self.NULL.left = None |
|||
self.NULL.right = None |
|||
self.root = self.NULL |
|||
# Insert New Node |
|||
def insertNode(self, key): |
|||
node = Node(key) |
|||
node.parent = None |
|||
node.val = key |
|||
node.left = self.NULL |
|||
node.right = self.NULL |
|||
node.color = 1 # Set root colour as Red |
|||
y = None |
|||
x = self.root |
|||
while x != self.NULL : # Find position for new node |
|||
y = x |
|||
if node.val < x.val : |
|||
x = x.left |
|||
else : |
|||
x = x.right |
|||
node.parent = y # Set parent of Node as y |
|||
if y == None : # If parent i.e, is none then it is root node |
|||
self.root = node |
|||
elif node.val < y.val : # Check if it is right Node or Left Node by checking the value |
|||
y.left = node |
|||
else : |
|||
y.right = node |
|||
if node.parent == None : # Root node is always Black |
|||
node.color = 0 |
|||
return |
|||
if node.parent.parent == None : # If parent of node is Root Node |
|||
return |
|||
self.fixInsert ( node ) # Else call for Fix Up |
|||
def minimum(self, node): |
|||
while node.left != self.NULL: |
|||
node = node.left |
|||
return node |
|||
# Code for left rotate |
|||
def LR ( self , x ) : |
|||
y = x.right # Y = Right child of x |
|||
x.right = y.left # Change right child of x to left child of y |
|||
if y.left != self.NULL : |
|||
y.left.parent = x |
|||
y.parent = x.parent # Change parent of y as parent of x |
|||
if x.parent == None : # If parent of x == None ie. root node |
|||
self.root = y # Set y as root |
|||
elif x == x.parent.left : |
|||
x.parent.left = y |
|||
else : |
|||
x.parent.right = y |
|||
y.left = x |
|||
x.parent = y |
|||
# Code for right rotate |
|||
def RR ( self , x ) : |
|||
y = x.left # Y = Left child of x |
|||
x.left = y.right # Change left child of x to right child of y |
|||
if y.right != self.NULL : |
|||
y.right.parent = x |
|||
y.parent = x.parent # Change parent of y as parent of x |
|||
if x.parent == None : # If x is root node |
|||
self.root = y # Set y as root |
|||
elif x == x.parent.right : |
|||
x.parent.right = y |
|||
else : |
|||
x.parent.left = y |
|||
y.right = x |
|||
x.parent = y |
|||
# Fix Up Insertion |
|||
def fixInsert(self, k): |
|||
while k.parent.color == 1: # While parent is red |
|||
if k.parent == k.parent.parent.right: # if parent is right child of its parent |
|||
u = k.parent.parent.left # Left child of grandparent |
|||
if u.color == 1: # if color of left child of grandparent i.e, uncle node is red |
|||
u.color = 0 # Set both children of grandparent node as black |
|||
k.parent.color = 0 |
|||
k.parent.parent.color = 1 # Set grandparent node as Red |
|||
k = k.parent.parent # Repeat the algo with Parent node to check conflicts |
|||
else: |
|||
if k == k.parent.left: # If k is left child of it's parent |
|||
k = k.parent |
|||
self.RR(k) # Call for right rotation |
|||
k.parent.color = 0 |
|||
k.parent.parent.color = 1 |
|||
self.LR(k.parent.parent) |
|||
else: # if parent is left child of its parent |
|||
u = k.parent.parent.right # Right child of grandparent |
|||
if u.color == 1: # if color of right child of grandparent i.e, uncle node is red |
|||
u.color = 0 # Set color of childs as black |
|||
k.parent.color = 0 |
|||
k.parent.parent.color = 1 # set color of grandparent as Red |
|||
k = k.parent.parent # Repeat algo on grandparent to remove conflicts |
|||
else: |
|||
if k == k.parent.right: # if k is right child of its parent |
|||
k = k.parent |
|||
self.LR(k) # Call left rotate on parent of k |
|||
k.parent.color = 0 |
|||
k.parent.parent.color = 1 |
|||
self.RR(k.parent.parent) # Call right rotate on grandparent |
|||
if k == self.root: # If k reaches root then break |
|||
break |
|||
self.root.color = 0 # Set color of root as black |
|||
# Function to fix issues after deletion |
|||
def fixDelete ( self , x ) : |
|||
while x != self.root and x.color == 0 : # Repeat until x reaches nodes and color of x is black |
|||
if x == x.parent.left : # If x is left child of its parent |
|||
s = x.parent.right # Sibling of x |
|||
if s.color == 1 : # if sibling is red |
|||
s.color = 0 # Set its color to black |
|||
x.parent.color = 1 # Make its parent red |
|||
self.LR ( x.parent ) # Call for left rotate on parent of x |
|||
s = x.parent.right |
|||
# If both the child are black |
|||
if s.left.color == 0 and s.right.color == 0 : |
|||
s.color = 1 # Set color of s as red |
|||
x = x.parent |
|||
else : |
|||
if s.right.color == 0 : # If right child of s is black |
|||
s.left.color = 0 # set left child of s as black |
|||
s.color = 1 # set color of s as red |
|||
self.RR ( s ) # call right rotation on x |
|||
s = x.parent.right |
|||
s.color = x.parent.color |
|||
x.parent.color = 0 # Set parent of x as black |
|||
s.right.color = 0 |
|||
self.LR ( x.parent ) # call left rotation on parent of x |
|||
x = self.root |
|||
else : # If x is right child of its parent |
|||
s = x.parent.left # Sibling of x |
|||
if s.color == 1 : # if sibling is red |
|||
s.color = 0 # Set its color to black |
|||
x.parent.color = 1 # Make its parent red |
|||
self.RR ( x.parent ) # Call for right rotate on parent of x |
|||
s = x.parent.left |
|||
if s.right.color == 0 and s.right.color == 0 : |
|||
s.color = 1 |
|||
x = x.parent |
|||
else : |
|||
if s.left.color == 0 : # If left child of s is black |
|||
s.right.color = 0 # set right child of s as black |
|||
s.color = 1 |
|||
self.LR ( s ) # call left rotation on x |
|||
s = x.parent.left |
|||
s.color = x.parent.color |
|||
x.parent.color = 0 |
|||
s.left.color = 0 |
|||
self.RR ( x.parent ) |
|||
x = self.root |
|||
x.color = 0 |
|||
# Function to transplant nodes |
|||
def __rb_transplant ( self , u , v ) : |
|||
if u.parent == None : |
|||
self.root = v |
|||
elif u == u.parent.left : |
|||
u.parent.left = v |
|||
else : |
|||
u.parent.right = v |
|||
v.parent = u.parent |
|||
# Function to handle deletion |
|||
def delete_node_helper ( self , node , key ) : |
|||
z = self.NULL |
|||
while node != self.NULL : # Search for the node having that value/ key and store it in 'z' |
|||
if node.val == key : |
|||
z = node |
|||
if node.val <= key : |
|||
node = node.right |
|||
else : |
|||
node = node.left |
|||
if z == self.NULL : # If Kwy is not present then deletion not possible so return |
|||
print ( "Value not present in Tree !!" ) |
|||
return |
|||
y = z |
|||
y_original_color = y.color # Store the color of z- node |
|||
if z.left == self.NULL : # If left child of z is NULL |
|||
x = z.right # Assign right child of z to x |
|||
self.__rb_transplant ( z , z.right ) # Transplant Node to be deleted with x |
|||
elif (z.right == self.NULL) : # If right child of z is NULL |
|||
x = z.left # Assign left child of z to x |
|||
self.__rb_transplant ( z , z.left ) # Transplant Node to be deleted with x |
|||
else : # If z has both the child nodes |
|||
y = self.minimum ( z.right ) # Find minimum of the right sub tree |
|||
y_original_color = y.color # Store color of y |
|||
x = y.right |
|||
if y.parent == z : # If y is child of z |
|||
x.parent = y # Set parent of x as y |
|||
else : |
|||
self.__rb_transplant ( y , y.right ) |
|||
y.right = z.right |
|||
y.right.parent = y |
|||
self.__rb_transplant ( z , y ) |
|||
y.left = z.left |
|||
y.left.parent = y |
|||
y.color = z.color |
|||
if y_original_color == 0 : # If color is black then fixing is needed |
|||
self.fixDelete ( x ) |
|||
# Deletion of node |
|||
def delete_node ( self , val ) : |
|||
self.delete_node_helper ( self.root , val ) # Call for deletion |
|||
# Function to print |
|||
def __printCall ( self , node , indent , last ) : |
|||
if node != self.NULL : |
|||
print(indent, end=' ') |
|||
if last : |
|||
print ("R----",end= ' ') |
|||
indent += " " |
|||
else : |
|||
print("L----",end=' ') |
|||
indent += "| " |
|||
s_color = "RED" if node.color == 1 else "BLACK" |
|||
print ( str ( node.val ) + "(" + s_color + ")" ) |
|||
self.__printCall ( node.left , indent , False ) |
|||
self.__printCall ( node.right , indent , True ) |
|||
# Function to call print |
|||
def print_tree ( self ) : |
|||
self.__printCall ( self.root , "" , True ) |
|||
if __name__ == "__main__": |
|||
bst = RBTree() |
|||
print("State of the tree after inserting the 30 keys:") |
|||
for x in range(1, 30): |
|||
bst.insertNode(x) |
|||
bst.print_tree() |
|||
print("\nState of the tree after deleting the 15 keys:") |
|||
for x in range(1, 15): |
|||
bst.delete_node(x) |
|||
bst.print_tree() |
|||
</lang> |
|||
{{out}} |
|||
<pre>State of the tree after inserting the 30 keys: |
|||
R---- 8(BLACK) |
|||
L---- 4(BLACK) |
|||
| L---- 2(BLACK) |
|||
| | L---- 1(BLACK) |
|||
| | R---- 3(BLACK) |
|||
| R---- 6(BLACK) |
|||
| L---- 5(BLACK) |
|||
| R---- 7(BLACK) |
|||
R---- 16(BLACK) |
|||
L---- 12(RED) |
|||
| L---- 10(BLACK) |
|||
| | L---- 9(BLACK) |
|||
| | R---- 11(BLACK) |
|||
| R---- 14(BLACK) |
|||
| L---- 13(BLACK) |
|||
| R---- 15(BLACK) |
|||
R---- 20(RED) |
|||
L---- 18(BLACK) |
|||
| L---- 17(BLACK) |
|||
| R---- 19(BLACK) |
|||
R---- 24(BLACK) |
|||
L---- 22(RED) |
|||
| L---- 21(BLACK) |
|||
| R---- 23(BLACK) |
|||
R---- 26(RED) |
|||
L---- 25(BLACK) |
|||
R---- 28(BLACK) |
|||
L---- 27(RED) |
|||
R---- 29(RED) |
|||
State of the tree after deleting the 15 keys: |
|||
R---- 20(BLACK) |
|||
L---- 16(BLACK) |
|||
| L---- 15(BLACK) |
|||
| R---- 18(RED) |
|||
| L---- 17(BLACK) |
|||
| R---- 19(BLACK) |
|||
R---- 24(BLACK) |
|||
L---- 22(RED) |
|||
| L---- 21(BLACK) |
|||
| R---- 23(BLACK) |
|||
R---- 26(RED) |
|||
L---- 25(BLACK) |
|||
R---- 28(BLACK) |
|||
L---- 27(RED) |
|||
R---- 29(RED)</pre> |
|||
=={{header|Wren}}== |
=={{header|Wren}}== |