Red black tree sort

From Rosetta Code
Revision as of 02:32, 20 June 2022 by Rdm (talk | contribs) (problems)
Red black tree sort is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Implement red-black tree sorting of fixed width integers. Here, the left branch will only contain nodes with a smaller key and the right branch will only contain nodes with a larger key.

Start with an empty tree, add 30 nodes each with arbitrary (aka "random") keys, then traverse the tree, printing the values from the left node, the key value, then the values from the right node, displaying their value and their color (red or black). Since we are using a red-black tree here, this would eliminate any duplicate values.

Then delete an arbitrary 15 nodes and display the resulting tree.

You may use an implementation at Algebraic data types as a starting point, if you find that helpful.

Please verify the integrity of the red-black tree after every insert and after every delete.


F#

The Functions

This task extends Algebraic data types#F.23 adding the following functions: <lang fsharp> // Red black tree sort. Nigel Galloway: June 17th., 2022 let fromSeq n=n|>Seq.fold(fun n g->insert g n) Empty let toSeq g=let rec fN g=seq{match g with N(i,g,e,l)->yield l; yield! fN g; yield! fN e |_->()} in fN g let delSeq n g=toSeq g|>Seq.except n|>fromSeq let rec printN n s t=match n with N(i,g,e,l)->printN g (s+" ") "L";printfn "%s %s %A %d" s t i l; printN e (s+" ") "R" |_->() </lang>

The Task

<lang fsharp> let n=fromSeq [85; 57; 51; 50; 86; 39; 95; 49; 44; 48; 21; 83; 11; 59; 88; 66; 4; 40; 24; 82; 63; 22; 37; 32; 91; 74; 28; 75; 62; 81] printfn "Populated Red Black Tree"; printN n "" "X" let g=delSeq [32; 40; 57; 63; 66; 75; 86; 59; 83; 51; 24; 62; 82; 39; 37] n printfn "\nRed Black Tree after deletions"; printN g "" "X" </lang>

Output:
Populated Red Black Tree
                     L Red 4
                 L Black 11
             L Black 21
                 R Black 22
         L Red 24
                         L Red 28
                     L Black 32
                 L Red 37
                     R Black 39
                         R Red 40
             R Black 44
                     L Red 48
                 R Black 49
     L Black 50
             L Black 51
         R Black 57
                 L Black 59
             R Red 62
                 R Black 63
 X Black 66
             L Black 74
         L Black 75
                 L Red 81
             R Black 82
     R Black 83
             L Black 85
         R Black 86
                 L Black 88
             R Red 91
                 R Black 95

Red Black Tree after deletions
             L Red 4
         L Black 11
     L Black 21
         R Black 22
             R Red 28
 X Black 44
             L Black 48
         L Black 49
             R Black 50
     R Red 74
             L Black 81
         R Black 85
                 L Red 88
             R Black 91
                 R Red 95

FreeBASIC

Code originally by AGS. https://www.freebasic.net/forum/viewtopic.php?t=16113 <lang freebasic>#define NULL Cast(Any Ptr,0)

Enum nodecolor

   BLACK = 0
   RED = 1

End Enum

Type RBNode

   Dim izda As RBNode Ptr
   Dim dcha As RBNode Ptr
   Dim parent As RBNode Ptr
   Dim kolor As nodecolor
   Dim key As Integer
   Dim value As String
   Dim nonzero As Integer
   Declare Constructor(Byval key As Integer = 0, value As String = "", Byval clr As nodecolor = RED)
   Declare Destructor()

End Type

Constructor RBNode(Byval key As Integer, value As String, Byval clr As nodecolor = RED)

   This.key = key
   This.value = value
   This.izda = NULL
   This.dcha = NULL
   This.parent = NULL
   This.kolor = clr
   This.nonzero = 1

End Constructor

Destructor RBNode()

End Destructor

Function integer_compare(Byval key1 As Integer, Byval key2 As Integer) As Integer

   If (key1 = key2) Then
       Return 0
   Elseif (key1 < key2) Then
       Return -1
   Elseif (key1 > key2) Then
       Return 1
   End If

End Function

Type RBTree

   Dim sentinel As RBNode Ptr
   Dim root As RBNode Ptr
   Dim count As Integer 
   Dim Compare As Function(Byval key1 As Integer, Byval key2 As Integer) As Integer
   Declare Constructor(Byval cmp As Function(Byval key1 As Integer, Byval key2 As Integer) As Integer)
   Declare Sub rotateLeft(Byval x As RBNode Ptr)
   Declare Sub rotateRight(Byval x As RBNode Ptr)
   Declare Sub insertFixup(Byval x As RBNode Ptr) 
   Declare Function insertNode(Byval key As Integer, value As String) As RBNode Ptr
   Declare Sub deleteFixup(Byval x As RBNode Ptr)  
   Declare Sub deleteNode(Byval z As RBNode Ptr)
   Declare Function findNode(Byval key As Integer) As RBNode Ptr
   Declare Destructor() 

End Type

Constructor RBTree(Byval cmp As Function(Byval key1 As Integer, Byval key2 As Integer) As Integer)

   This.sentinel = New RBNode(0,"",BLACK)
   This.sentinel->izda = sentinel
   This.sentinel->dcha = sentinel
   This.root = This.sentinel
   This.count = 0
   This.Compare = cmp

End Constructor


Destructor RBTree()

   'The tree is transformed into a tree in which 
   'left children are always leaves. This is done by rotation. 
   'After rotating any left child is a leaf (not a tree)
   'so a izda child can simply be deleted.  
   'Usually a stack is used to keep track of what nodes have
   'been removed. By using rotation there is no need for a stack.
   Dim parent As RBNode Ptr
   Dim child As RBNode Ptr
   
   If (This.root <> This.sentinel Andalso This.root <> NULL) Then
       parent = This.root
       While (parent <> This.sentinel)    
           If (parent->izda = This.sentinel) Then        
               child = parent->dcha
               Delete parent
               parent = 0
           Else        
               'rotate
               child = parent->izda
               parent->izda = child->dcha
               child->dcha = parent
           End If
           parent = child
       Wend  
   Else
       If (This.sentinel <> 0) Then
           Delete This.sentinel
           This.sentinel = 0
       End If        
   End If

End Destructor

Sub RBTree.rotateLeft(Byval x As RBNode Ptr)

   'rotate node x to right
   
   Var y = x->dcha
   
   'establish x->dcha link
   x->dcha = y->izda
   If (y->izda <> This.sentinel) Then
       y->izda->parent = x
   End If
   
   'establish y->parent link
   If (y <> This.sentinel) Then
       y->parent = x->parent
   End If
   If (x->parent) Then
       If (x = x->parent->izda) Then
           x->parent->izda = y
       Else
           x->parent->dcha = y
       End If
   Else
       This.root = y
   End If
   
   'link x and y
   y->izda = x
   If (x <> This.sentinel) Then
       x->parent = y
   End If

End Sub

Sub RBTree.rotateRight(Byval x As RBNode Ptr)

   'rotate node x to right
   
   Var y = x->izda
   
   ' establish x->left link
   x->izda = y->dcha
   If (y->dcha <> This.sentinel) Then
       y->dcha->parent = x
   End If
   
   ' establish y->parent link
   If (y <> This.sentinel) Then
       y->parent = x->parent
   End If
   If (x->parent) Then
       If (x = x->parent->dcha) Then
           x->parent->dcha = y
       Else
           x->parent->izda = y
       End If
   Else
       This.root = y
   End If
   
   'link x and y
   y->dcha = x
   If (x <> This.sentinel) Then
       x->parent = y
   End If

End Sub

Sub RBTree.insertFixup(Byval x As RBNode Ptr)

   'maintain tree balance after inserting node x
   
   'check Red-Black properties
   While (x <> This.Root Andalso x->parent->kolor = RED)
       'we have a violation
       If (x->parent = x->parent->parent->izda) Then
           Var y = x->parent->parent->dcha
           If (y->kolor = RED) Then
               'uncle is RED
               x->parent->kolor = BLACK
               y->kolor = BLACK
               x->parent->parent->kolor = RED
               x = x->parent->parent
           Else
               'uncle is BLACK
               If (x = x->parent->dcha) Then
                   'make x a izda child
                   x = x->parent
                   This.rotateLeft(x)
               End If
               'recolor and rotate
               x->parent->kolor = BLACK
               x->parent->parent->kolor = RED
               This.rotateRight(x->parent->parent)
           End If
       Else
           ' mirror image of above code
           Var y = x->parent->parent->izda
           If (y->kolor = RED) Then
               ' uncle is RED
               x->parent->kolor = BLACK
               y->kolor = BLACK
               x->parent->parent->kolor = RED
               x = x->parent->parent
           Else
               ' uncle is BLACK
               If (x = x->parent->izda) Then
                   x = x->parent
                   This.rotateRight(x)
               End If
               x->parent->kolor = BLACK
               x->parent->parent->kolor = RED
               This.rotateLeft(x->parent->parent)
           End If
       End If
   Wend
   This.root->kolor = BLACK

End Sub

Function RBTree.insertNode(Byval key As Integer, value As String) As RBNode Ptr

   'Insert a node in the RBTree
   
   'find where node belongs
   Dim current As RBNode Ptr = This.root
   Dim parent As RBNode Ptr
   While (current <> This.sentinel)
       Var rc = This.Compare(key, current->key)
       If (rc = 0) Then Return current
       parent = current
       If (rc < 0) Then
           current = current->izda
       Else
           current = current->dcha
       End If
   Wend
   ' setup new node
   Dim x As RBNode Ptr = New RBNode(key, value)
   x->izda  = This.sentinel
   x->dcha = This.sentinel
   x->parent = parent
   
   This.count = This.count + 1
   
   ' insert node in tree
   If (parent) Then
       If (This.Compare(key, parent->key) < 0) Then
           parent->izda = x
       Else
           parent->dcha = x
       End If
   Else
       This.root = x
   End If
   
   This.insertFixup(x)
   Return x

End Function

Sub RBTree.deleteFixup(Byval x As RBNode Ptr)

   'maintain tree balance after deleting node x
   
   Dim w As RBNode Ptr
   While (x <> This.root Andalso x->kolor = BLACK)
       If (x = x->parent->izda) Then
           w = x->parent->dcha
           If (w->kolor = RED) Then
               w->kolor = BLACK
               x->parent->kolor = RED
               This.rotateLeft(x->parent)
               w = x->parent->dcha
           End If
           
           If (w->izda->kolor = BLACK And w->dcha->kolor = BLACK) Then
               w->kolor = RED
               x = x->parent
           Else
               If (w->dcha->kolor = BLACK) Then
                   w->izda->kolor = BLACK
                   w->kolor = RED
                   This.rotateRight(w)
                   w = x->parent->dcha
               End If
               
               w->kolor = x->parent->kolor
               x->parent->kolor = BLACK
               w->dcha->kolor = BLACK
               This.rotateLeft(x->parent)
               x = This.root
           End If
       Else
           w = x->parent->izda
           If (w->kolor = RED) Then
               w->kolor = BLACK
               x->parent->kolor = RED
               This.rotateRight(x->parent)
               w = x->parent->izda
           End If
           
           If (w->dcha->kolor = BLACK And w->izda->kolor = BLACK) Then
               w->kolor = RED
               x = x->parent
           Else
               If (w->izda->kolor = BLACK) Then
                   w->dcha->kolor = BLACK
                   w->kolor = RED
                   This.rotateLeft(w)
                   w = x->parent->izda
               End If
               
               w->kolor = x->parent->kolor
               x->parent->kolor = BLACK
               w->izda->kolor = BLACK
               This.rotateRight(x->parent)
               x = This.root
           End If
       End If
   Wend
   x->kolor = BLACK

End Sub

Sub RBTree.deleteNode(Byval z As RBNode Ptr)

   'delete node z from tree
   
   Dim y As RBNode Ptr
   Dim x As RBNode Ptr
   
   If (0 =  z Orelse z = This.sentinel) Then Return
   
   If (z->izda = This.sentinel Orelse z->dcha = This.sentinel) Then
       'y has a This.sentinel node as a child
       y = z
   Else
       'find tree successor with a This.sentinel node as a child
       y = z->dcha
       While (y->izda <> This.sentinel)
           y = y->izda
       Wend
   End If
   
   'x is y's only child
   If (y->izda <> This.sentinel) Then
       x = y->izda
   Else
       x = y->dcha
   End If
   
   'remove y from the parent chain
   x->parent = y->parent
   If (y->parent) Then
       If (y = y->parent->izda) Then
           y->parent->izda = x
       Else
           y->parent->dcha = x
       End If
   Else
       This.root = x
   End If
   
   If (y <> z) Then  
       z->key = y->key
       z->value = y->value
   End If
   
   If (y->kolor = BLACK) Then
       This.deleteFixup(x)
   End If
   
   Delete y
   
   This.count = This.count - 1

End Sub

Function RBtree.findNode(Byval key As Integer) As RBNode Ptr

   'find node with key equal to key
   Var current = This.root
   
   While (current <> This.sentinel)
       Var rc = This.Compare(key, current->key)
       If (rc = 0) Then
           Return current
       Else
           If (rc < 0) Then
               current = current->izda
           Else
               current = current->dcha
           End If
       End If
   Wend
   Return 0

End Function

Type GraphicsNode

   Dim node As RBNode Ptr  
   Dim lvl As Ubyte
   Dim nxt As GraphicsNode Ptr
   Dim prev As GraphicsNode Ptr
   Dim x As Uinteger
   Dim y As Uinteger

End Type

Type NodeQueue

   Dim startx As Integer
   Dim starty As Integer
   Dim first As GraphicsNode Ptr
   Dim last  As GraphicsNode Ptr
   Dim levels(2 To 11) As Integer => {100,50,25,12,10,10,10,10,10}
   Dim count As Integer
   Declare Constructor
   Declare Destructor
   Declare Function Enqueue(Byref item As GraphicsNode Ptr) As Integer
   Declare Function Dequeue(Byref item As GraphicsNode Ptr) As GraphicsNode Ptr
   Declare Sub PrintNode(Byval item As GraphicsNode Ptr, Byval x As Integer, Byval y As Integer)
   Declare Sub PrintTree(Byval tree As RBTree Ptr)

End Type

Constructor NodeQueue() Draw first node in the middle of the screen '(just below the top of the screen)

   This.startx = 350
   This.starty = 100
   This.first = NULL
   This.last = NULL  
   This.count = 1
   '800x600, 32 bits kolor
   Screen 19,32
   color , Rgb(255,255,155)
   Cls
   WindowTitle "Red black tree sort"

End Constructor

Destructor NodeQueue()

End Destructor

Function NodeQueue.Enqueue(Byref item As GraphicsNode Ptr) As Integer

   'Insertion into an empty que
   If (This.first = NULL) Then
       This.first = item
       This.last = item
       This.Count += 1
       Return 0
   Else
       Var tmp = This.last
       This.last = item
       This.last->prev = tmp
       tmp->nxt = This.last
       This.last->nxt = NULL
       This.Count += 1
       Return 0
   End If
   
   Return -1    

End Function

Function NodeQueue.Dequeue(Byref item As GraphicsNode Ptr) As GraphicsNode Ptr

   'Dequeueing from an empty queue or a queue with one node
   If (This.last = This.first) Then
       'Dequeueing from an empty queue
       If (This.last = NULL) Then
           This.Count -= 1
           Return NULL
       Else      
           'Dequeueing from a queue with one node
           item->node = This.First->node
           item->x = This.First->x
           item->y = This.First->y
           item->lvl = This.first->lvl      
           Delete This.first
           This.first = NULL
           This.last = NULL
           This.Count -= 1
           Return item
       End If
   Else  
       'Dequeueing from a queue with more than one node
       Var tmp = This.Last
       item->node = This.Last->node
       item->x = This.Last->x
       item->y = This.Last->y
       item->lvl = This.Last->lvl      
       This.last = This.last->prev
       This.last->nxt = NULL
       Delete tmp
       Return item
   End If
   Return NULL

End Function

Sub NodeQueue.PrintNode(Byval item As GraphicsNode Ptr, Byval x As Integer, Byval y As Integer)

   'Draw a black line from parent node to child node
   Line (x,y)-(item->x,item->y), Rgb(0,0,0)
   'Draw node (either red or black)
   If (item->node->kolor = RED) Then
       Circle (item->x,item->y),5, Rgb(255,0,0),,,,F
   Else
       Circle (item->x,item->y),5, Rgb(0,0,0),,,,F
   End If
   Draw String (item->x,item->y - 40), Str(item->node->key), Rgb(0,0,0)
   Draw String (item->x-8,item->y - 25),"""" & item->node->value & """", Rgb(0,0,0)

End Sub

Sub NodeQueue.PrintTree(Byval tree As RBTree Ptr)

   Dim item As GraphicsNode Ptr
   
   Dim current As GraphicsNode Ptr = New GraphicsNode  
   Dim tmp As GraphicsNode Ptr
   Dim lvl As Integer = 1
   Dim x As Integer = This.startx
   Dim y As Integer = This.starty
   
   'check for empty tree
   If (tree->root = tree->sentinel) Then Return
   
   'Start with printing the root
   current->node = tree->root
   current->x = x
   current->y = y
   current->lvl = lvl  
   This.PrintNode(current,x,y)
   Do
       'Print izda node (position it at izda side of current node)
       If (current->node->izda <> tree->sentinel) Then
           item = New GraphicsNode
           item->lvl = lvl + 1      
           If (item->lvl <= 9) Then
               item->x = x - This.levels(lvl+1)
           Else
               item->x = x - 10
           End If
           item->y = y + 50
           item->node = current->node->izda
           This.PrintNode(item,x,y)
           This.Enqueue(item)
       End If
       'Print dcha node (position it at dcha side of current node
       If (current->node->dcha <> tree->sentinel) Then
           item = New GraphicsNode
           item->lvl = lvl + 1
           If (item->lvl <= 9) Then
               item->x = x + This.levels(lvl+1)
           Else
               item->x = x + 10
           End If
           item->y = y + 50
           item->node = current->node->dcha
           This.PrintNode(item,x,y)
           This.Enqueue(item)
       End If
       'Continue drawing from first node in the queue
       'Nodes in izda tree will be drawn first as these are put in
       'the queue first
       Var tmp = This.Dequeue(current)
       'If count smaller then entire tree has been drawn
       If (This.count < 1) Then Exit Do
       x = current->x
       y = current->y
       lvl = current->lvl
   Loop

End Sub

Dim x As Integer Ptr Dim i As Integer Var tree = New RBTree(@integer_compare)

Open Cons For Output As #1 For i = 0 To 29

   Print #1, "Insert "; i
   tree->Insertnode(i,Str(i))
   Sleep()
   Dim print_tree As NodeQueue Ptr
   print_tree = New NodeQueue
   print_tree->PrintTree(tree)
   Delete print_tree  

Next i

Print #1, !"\nStarting Deletion after keypress" Var print_tree = New NodeQueue print_tree->PrintTree(tree) Sleep() Delete print_tree

randomize timer For i = 0 To 14

   Dim as integer j = int(rnd * 15) + int(rnd * 16)
   Print #1, "Delete"; j
   Var n = tree->FindNode(j)
   If (n) Then tree->Deletenode(n)
   Sleep()
   Dim print_tree As NodeQueue Ptr
   print_tree = New NodeQueue
   print_tree->PrintTree(tree)
   Delete print_tree  

Next i

Bsave "FreeBASIC_Red-black-tree_sort.bmp", 0 Print #1, !"\nEnding program after keypress" Sleep() Close #1 Delete tree</lang>

Output:

FreeBasic Red black tree sort image

Julia

See Red_black_tree_sort/Julia.

Phix

See Red_black_tree_sort/Phix.

Python

This is based on the code of Shivali Bhadaniya [1], which I thought was reasonably intelligible. <lang python>#!/usr/bin/python

  1. 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
  1. 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>

Output:
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)

Wren

See Red_black_tree_sort/Wren.