Guest User

Untitled

a guest
Jul 19th, 2018
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.21 KB | None | 0 0
  1. #!/usr/bin/env ruby
  2. # Red/Black tree implementation based on
  3. # Algorithms in C++, Sedgewick
  4. # Introduction To Algorithms Cormen, Thomas H. / Leiserson, Charles E . / Rivest, Ronald L . The MIT Press 07/1990
  5. class RedBlackTree
  6. RED = 0
  7. BLACK = 1
  8.  
  9. attr_reader :value, :color
  10.  
  11. def initialize(value = nil)
  12. @left = nil
  13. @right = nil
  14. @value = value
  15. @color = RED
  16. end
  17.  
  18. def to_s
  19. "[#{@value}, #{@color == 0 ? 'RED' : 'BLACK'}]"
  20. end
  21.  
  22. def find(key)
  23. result = nil
  24. if key == @value
  25. result = self
  26. elsif key < @value
  27. result = @left.find(key) if @left
  28. else
  29. result = @right.find(key) if @right
  30. end
  31. result
  32. end
  33.  
  34. def print(&block)
  35. @right.print_(1, &block) if @right
  36. yield self, 0
  37. @left.print_(1, &block) if @left
  38. end
  39.  
  40. def insert(value)
  41. insert_node(value, 0)
  42. @color = BLACK
  43. end
  44.  
  45. protected
  46. attr_accessor :left, :right
  47. attr_writer :color
  48.  
  49. def print_(depth, &block)
  50. @right.print_(depth + 1, &block) if @right
  51. yield self, depth
  52. @left.print_(depth + 1, &block) if @left
  53. end
  54.  
  55. def copy(node)
  56. @left = node.left
  57. @right = node.right
  58. @value = node.value
  59. @color = node.color
  60. end
  61.  
  62. def insert_node_left(value, color)
  63. unless @left
  64. @left = RedBlackTree.new(value)
  65. else
  66. @left.insert_node(value, color)
  67. end
  68. end
  69.  
  70. def insert_node_right(value,color)
  71. unless @right
  72. @right = RedBlackTree.new(value)
  73. else
  74. @right.insert_node(value, color)
  75. end
  76. end
  77.  
  78. def left_rotate
  79. return nil unless @right
  80.  
  81. # make the changes in a copy of current node __self
  82. # on return, the caller will copy in 'me' to current node
  83. me = RedBlackTree.new
  84. me.copy(self)
  85. node = me.right
  86. me.right = node.left
  87. node.left = me
  88. node
  89. end
  90.  
  91. def right_rotate
  92. return nil unless @left
  93.  
  94. # make the changes in a copy of current node __self
  95. # on return, the caller will copy in 'me' to current node
  96. me = RedBlackTree.new
  97. me.copy(self)
  98. node = me.left
  99. me.left = node.right
  100. node.right = me
  101. node
  102. end
  103.  
  104. def insert_node(value, color)
  105. # if current node is a 4 node, split it by flipping its colors
  106. # if both children of this node are red, change this one to red
  107. # and the children to black
  108. l = @left
  109. r = @right
  110. if l && l.color == RED && r && r.color == RED
  111. @color = RED
  112. l.color = r.color = BLACK
  113. end
  114.  
  115. # go left or right depending on key relationship
  116. if value < @value then
  117. # recursively insert
  118. insert_node_left(value, 0)
  119.  
  120. # on the way back up check if a rotation is needed
  121. # if search path has two red links with same orientation
  122. # do a single rotation and flip the color bits
  123. l = @left
  124. if @color == RED && l && l.color == RED && color == 1
  125. node = right_rotate
  126. copy(node) if node
  127. end
  128.  
  129. # flip the color bits
  130. l = @left
  131. if l && l.left && l.color == RED && l.left.color == RED
  132. node = right_rotate
  133. copy(node) if node
  134. @color = BLACK
  135. @right.color = RED if @right
  136. end
  137. else
  138. insert_node_right(value, 1)
  139.  
  140. # on the way back up check if a rotation is needed
  141. # if search path has two red links with same orientation
  142. # do a single rotation and flip the color bits
  143. r = @right
  144. if @color == RED && r && r.color == RED && color == 0
  145. node = left_rotate
  146. copy(node) if node
  147. end
  148.  
  149. # flip the color bits
  150. r = @right
  151. if r && r.right && r.color == RED && r.right.color == RED
  152. node = left_rotate
  153. copy(node) if node
  154. @color = BLACK
  155. @left.color = RED if @left
  156. end
  157. end
  158. end
  159. end
  160.  
  161.  
  162. def testRedBlackTree
  163. #nodelist = [11,4,8,14,17,6,9,7,16,15,13,5,19,18,12,10,3,20,1]
  164. nodelist = [2, 3, 4, 5]
  165. root = RedBlackTree.new(1)
  166. nodelist.each {|n| root.insert(n)}
  167.  
  168. # update 2006-01-30 removed lambda example because it is equivalueent to the block example
  169. # which is more idiomatic Ruby
  170.  
  171. # use a block directly
  172. root.print {|n,d| puts "#{' '*(d*2)}#{n}" }
  173. end
  174.  
  175. testRedBlackTree
Add Comment
Please, Sign In to add comment