Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added python version. Ruby version updated.

  • Loading branch information...
commit 2c2a034030bdb6ce2afe215a9deb2bc786a953fb 1 parent d72e4f6
@radarek radarek authored
View
2  .gitignore
@@ -0,0 +1,2 @@
+*.rbc
+*.pyc
View
39 bm_red_black_tree.py
@@ -0,0 +1,39 @@
+import sys
+import time
+import random
+from red_black_tree import RedBlackTree
+
+def rbt_bm():
+ start = time.time()
+ n = 100000
+
+ tree = RedBlackTree()
+
+ for i in xrange(0, n):
+ tree.add(i)
+ for i in xrange(0, n):
+ tree.delete(tree.root)
+
+ tree = RedBlackTree()
+ for i in xrange(0, n):
+ tree.add(random.randint(0, 999999))
+ for i in xrange(0, n):
+ tree.search(random.randint(0, 999999))
+ for key in tree.inorder_walk():
+ key + 1
+ for key in tree.reverse_inorder_walk():
+ key + 1
+ for i in xrange(0, n):
+ tree.maximum()
+ for i in xrange(0, n):
+ tree.minimum()
+
+ return time.time() - start
+
+if len(sys.argv) > 1:
+ n = int(sys.argv[1])
+else:
+ n = 5
+
+for i in xrange(0, n):
+ print "%02f" % rbt_bm()
View
11 bm_red_black_tree.rb
@@ -14,12 +14,13 @@ def rbt_bm
n.times { tree.delete(tree.root) }
tree = RedBlackTree.new
- n.times { tree.insert(RedBlackTree::Node.new(rand(100_000))) }
+ #n.times { tree.insert(RedBlackTree::Node.new(rand(100_000))) }
+ n.times { tree.add(rand(100_000)) }
n.times { tree.search(rand(100_000)) }
- tree.each {|node| node.key + 1 }
- tree.inorder_walk {|node| node.key + 1 }
- tree.reverse_each {|node| node.key + 1 }
- tree.reverse_inorder_walk {|node| node.key + 1 }
+ #tree.each {|node| node.key + 1 }
+ tree.inorder_walk {|key| key + 1 }
+ #tree.reverse_each {|node| node.key + 1 }
+ tree.reverse_inorder_walk {|key| key + 1 }
n.times { tree.minimum }
n.times { tree.maximum }
View
305 red_black_tree.py
@@ -0,0 +1,305 @@
+class Node:
+ RED = 1
+ BLACK = 2
+ COLORS = [RED, BLACK]
+
+ def __init__(self, key, color = RED):
+ if not color in self.COLORS:
+ raise TypeError("Bad value for color parameter (%s)" % color)
+ self.color = color
+ self.key = key
+ self.left = self.right = self.parent = NilNode.instance()
+
+ def __str__(self, level = 0, indent = " "):
+ s = level * indent + str(self.key)
+ if self.left:
+ s = s + "\n" + self.left.__str__(level + 1, indent)
+ if self.right:
+ s = s + "\n" + self.right.__str__(level + 1, indent)
+ return s
+ #return "<Node @key=%s, @color=%s, @left=%s, @right=%s>" % (self.key, self.color, self.left, self.right)
+
+ def is_red(self):
+ return self.color == self.RED
+
+ def is_black(self):
+ return self.color == self.BLACK
+
+ def is_nil(self):
+ return False
+
+
+class NilNode(Node):
+ __instance__ = None
+
+ @classmethod
+ def instance(self):
+ if self.__instance__ is None:
+ self.__instance__ = NilNode()
+ return self.__instance__
+
+ def __init__(self):
+ self.color = Node.BLACK
+ self.key = None
+ self.left = self.right = self.parent = None
+
+ def is_nil(self):
+ return True
+
+class RedBlackTree:
+ def __init__(self):
+ self.root = NilNode.instance()
+ self.size = 0
+
+ def __str__(self):
+ return ("(root.size = %d)\n" % self.size) + str(self.root)
+
+ def add(self, key):
+ self.insert(Node(key))
+
+ #def del(key):
+
+
+ def insert(self, x):
+ self.__insert_helper(x)
+
+ x.color = Node.RED
+ while x != self.root and x.parent.color == Node.RED:
+ if x.parent == x.parent.parent.left:
+ y = x.parent.parent.right
+ if not y.is_nil() and y.color == Node.RED:
+ x.parent.color = Node.BLACK
+ y.color = Node.BLACK
+ x.parent.parent.color = Node.RED
+ x = x.parent.parent
+ else:
+ if x == x.parent.right:
+ x = x.parent
+ self.__left_rotate(x)
+ x.parent.color = Node.BLACK
+ x.parent.parent.color = Node.RED
+ self.__right_rotate(x.parent.parent)
+ else:
+ y = x.parent.parent.left
+ if not y.is_nil() and y.color == Node.RED:
+ x.parent.color = Node.BLACK
+ y.color = Node.BLACK
+ x.parent.parent.color = Node.RED
+ x = x.parent.parent
+ else:
+ if x == x.parent.left:
+ x = x.parent
+ self.__right_rotate(x)
+ x.parent.color = Node.BLACK
+ x.parent.parent.color = Node.RED
+ self.__left_rotate(x.parent.parent)
+ self.root.color = Node.BLACK
+
+ def delete(self, z):
+ if z.left.is_nil() or z.right.is_nil():
+ y = z
+ else:
+ y = self.successor(z)
+ if y.left.is_nil():
+ x = y.right
+ else:
+ x = y.left
+ x.parent = y.parent
+
+ if y.parent.is_nil():
+ self.root = x
+ else:
+ if y == y.parent.left:
+ y.parent.left = x
+ else:
+ y.parent.right = x
+
+ if y != z: z.key = y.key
+
+ if y.color == Node.BLACK:
+ self.__delete_fixup(x)
+
+ self.size -= 1
+ return y
+
+ def minimum(self, x = None):
+ if x is None: x = self.root
+ while not x.left.is_nil():
+ x = x.left
+ return x
+
+ def maximum(self, x = None):
+ if x is None: x = self.root
+ while not x.right.is_nil():
+ x = x.right
+ return x
+
+ def successor(self, x):
+ if not x.right.is_nil():
+ return self.minimum(x.right)
+ y = x.parent
+ while not y.is_nil() and x == y.right:
+ x = y
+ y = y.parent
+ return y
+
+ def predecessor(self, x):
+ if not x.left.is_nil():
+ return self.maximum(x.left)
+ y = x.parent
+ while not y.is_nil() and x == y.left:
+ x = y
+ y = y.parent
+ return y
+
+ def inorder_walk(self, x = None):
+ if x is None: x = self.root
+ x = self.minimum()
+ while not x.is_nil():
+ yield x.key
+ x = self.successor(x)
+
+ def reverse_inorder_walk(self, x = None):
+ if x is None: x = self.root
+ x = self.maximum()
+ while not x.is_nil():
+ yield x.key
+ x = self.predecessor(x)
+
+ def search(self, key, x = None):
+ if x is None: x = self.root
+ while not x.is_nil() and x.key != key:
+ if key < x.key:
+ x = x.left
+ else:
+ x = x.right
+ return x
+
+ def is_empty(self):
+ return self.root.is_nil()
+
+ def black_height(self, x = None):
+ if x is None: x = self.root
+ height = 0
+ while not x.is_nil():
+ x = x.left
+ if x.is_nil() or x.is_black():
+ height += 1
+ return height
+
+ def __left_rotate(self, x):
+ if x.right.is_nil():
+ raise "x.right is nil!"
+ y = x.right
+ x.right = y.left
+ if not y.left.is_nil(): y.left.parent = x
+ y.parent = x.parent
+ if x.parent.is_nil():
+ self.root = y
+ else:
+ if x == x.parent.left:
+ x.parent.left = y
+ else:
+ x.parent.right = y
+ y.left = x
+ x.parent = y
+
+ def __right_rotate(self, x):
+ if x.left.is_nil():
+ raise "x.left is nil!"
+ y = x.left
+ x.left = y.right
+ if not y.right.is_nil(): y.right.parent = x
+ y.parent = x.parent
+ if x.parent.is_nil():
+ self.root = y
+ else:
+ if x == x.parent.left:
+ x.parent.left = y
+ else:
+ x.parent.right = y
+ y.right = x
+ x.parent = y
+
+ def __insert_helper(self, z):
+ y = NilNode.instance()
+ x = self.root
+ while not x.is_nil():
+ y = x
+ if z.key < x.key:
+ x = x.left
+ else:
+ x = x.right
+
+ z.parent = y
+ if y.is_nil():
+ self.root = z
+ else:
+ if z.key < y.key:
+ y.left = z
+ else:
+ y.right = z
+
+ self.size += 1
+
+ def __delete_fixup(self, x):
+ while x != self.root and x.color == Node.BLACK:
+ if x == x.parent.left:
+ w = x.parent.right
+ if w.color == Node.RED:
+ w.color = Node.BLACK
+ x.parent.color = Node.RED
+ self.__left_rotate(x.parent)
+ w = x.parent.right
+ if w.left.color == Node.BLACK and w.right.color == Node.BLACK:
+ w.color = Node.RED
+ x = x.parent
+ else:
+ if w.right.color == Node.BLACK:
+ w.left.color = Node.BLACK
+ w.color = Node.RED
+ self.__right_rotate(w)
+ w = x.parent.right
+ w.color = x.parent.color
+ x.parent.color = Node.BLACK
+ w.right.color = Node.BLACK
+ self.__left_rotate(x.parent)
+ x = self.root
+ else:
+ w = x.parent.left
+ if w.color == Node.RED:
+ w.color = Node.BLACK
+ x.parent.color = Node.RED
+ self.__right_rotate(x.parent)
+ w = x.parent.left
+ if w.right.color == Node.BLACK and w.left.color == Node.BLACK:
+ w.color = Node.RED
+ x = x.parent
+ else:
+ if w.left.color == Node.BLACK:
+ w.right.color = Node.BLACK
+ w.color = Node.RED
+ self.__left_rotate(w)
+ w = x.parent.left
+ w.color = x.parent.color
+ x.parent.color = Node.BLACK
+ w.left.color = Node.BLACK
+ self.__right_rotate(x.parent)
+ x = root
+ x.color = Node.BLACK
+
+
+
+if __name__ == "__main__":
+ tree = RedBlackTree()
+ tree.add(10)
+ tree.add(3)
+ tree.add(7)
+ tree.add(4)
+ tree.add(20)
+ tree.add(15)
+
+ print tree
+
+ for key in tree.inorder_walk():
+ print "key = %s" % key
View
662 red_black_tree.rb
@@ -1,329 +1,333 @@
-# Algorithm based on "Introduction to Algorithms" by Cormen and others
-class RedBlackTree
- class Node
- attr_accessor :color
- attr_accessor :key
- attr_accessor :left
- attr_accessor :right
- attr_accessor :parent
-
- RED = :red
- BLACK = :black
- COLORS = [RED, BLACK].freeze
-
- def initialize(key, color = RED)
- raise ArgumentError, "Bad value for color parameter" unless COLORS.include?(color)
- @color = color
- @key = key
- @left = @right = @parent = NilNode.instance
- end
-
- def black?
- return color == BLACK
- end
-
- def red?
- return color == RED
- end
- end
-
- class NilNode < Node
- class << self
- private :new
- @instance = nil
-
- # it's not thread safe
- def instance
- if @instance.nil?
- @instance = new
-
- def instance
- return @instance
- end
- end
-
- return @instance
- end
- end
-
- def initialize
- self.color = BLACK
- self.key = 0
- self.left = nil
- self.right = nil
- self.parent = nil
- end
-
- def nil?
- return true
- end
- end
-
- include Enumerable
-
- attr_accessor :root
- attr_accessor :size
-
- def initialize
- self.root = NilNode.instance
- self.size = 0
- end
-
- def insert(x)
- insert_helper(x)
-
- x.color = Node::RED
- while x != root && x.parent.color == Node::RED
- if x.parent == x.parent.parent.left
- y = x.parent.parent.right
- if !y.nil? && y.color == Node::RED
- x.parent.color = Node::BLACK
- y.color = Node::BLACK
- x.parent.parent.color = Node::RED
- x = x.parent.parent
- else
- if x == x.parent.right
- x = x.parent
- left_rotate(x)
- end
- x.parent.color = Node::BLACK
- x.parent.parent.color = Node::RED
- right_rotate(x.parent.parent)
- end
- else
- y = x.parent.parent.left
- if !y.nil? && y.color == Node::RED
- x.parent.color = Node::BLACK
- y.color = Node::BLACK
- x.parent.parent.color = Node::RED
- x = x.parent.parent
- else
- if x == x.parent.left
- x = x.parent
- right_rotate(x)
- end
- x.parent.color = Node::BLACK
- x.parent.parent.color = Node::RED
- left_rotate(x.parent.parent)
- end
- end
- end
- root.color = Node::BLACK
- end
-
- alias << insert
-
- def delete(z)
- y = (z.left.nil? || z.right.nil?) ? z : successor(z)
- x = y.left.nil? ? y.right : y.left
- x.parent = y.parent
-
- if y.parent.nil?
- self.root = x
- else
- if y == y.parent.left
- y.parent.left = x
- else
- y.parent.right = x
- end
- end
-
- z.key = y.key if y != z
-
- if y.color == Node::BLACK
- delete_fixup(x)
- end
-
- self.size -= 1
- return y
- end
-
- def minimum(x = root)
- while !x.left.nil?
- x = x.left
- end
- return x
- end
-
- def maximum(x = root)
- while !x.right.nil?
- x = x.right
- end
- return x
- end
-
- def successor(x)
- if !x.right.nil?
- return minimum(x.right)
- end
- y = x.parent
- while !y.nil? && x == y.right
- x = y
- y = y.parent
- end
- return y
- end
-
- def predecessor(x)
- if !x.left.nil?
- return maximum(x.left)
- end
- y = x.parent
- while !y.nil? && x == y.left
- x = y
- y = y.parent
- end
- return y
- end
-
- def inorder_walk(x = root, &block)
- x = self.minimum
- while !x.nil?
- yield x
- x = successor(x)
- end
- end
-
- alias each inorder_walk
-
- def reverse_inorder_walk(x = root, &block)
- x = self.maximum
- while !x.nil?
- yield x
- x = predecessor(x)
- end
- end
-
- alias reverse_each reverse_inorder_walk
-
- def search(key, x = root)
- while !x.nil? && x.key != key
- key < x.key ? x = x.left : x = x.right
- end
- return x
- end
-
- def empty?
- return self.root.nil?
- end
-
- def black_height(x = root)
- height = 0
- while !x.nil?
- x = x.left
- height +=1 if x.nil? || x.black?
- end
- return height
- end
-
-private
-
- def left_rotate(x)
- raise "x.right is nil!" if x.right.nil?
- y = x.right
- x.right = y.left
- y.left.parent = x if !y.left.nil?
- y.parent = x.parent
- if x.parent.nil?
- self.root = y
- else
- if x == x.parent.left
- x.parent.left = y
- else
- x.parent.right = y
- end
- end
- y.left = x
- x.parent = y
- end
-
- def right_rotate(x)
- raise "x.left is nil!" if x.left.nil?
- y = x.left
- x.left = y.right
- y.right.parent = x if !y.right.nil?
- y.parent = x.parent
- if x.parent.nil?
- self.root = y
- else
- if x == x.parent.left
- x.parent.left = y
- else
- x.parent.right = y
- end
- end
- y.right = x
- x.parent = y
- end
-
- def insert_helper(z)
- y = NilNode.instance
- x = root
- while !x.nil?
- y = x
- z.key < x.key ? x = x.left : x = x.right
- end
- z.parent = y
- if y.nil?
- self.root = z
- else
- z.key < y.key ? y.left = z : y.right = z
- end
- self.size += 1
- end
-
- def delete_fixup(x)
- while x != root && x.color == Node::BLACK
- if x == x.parent.left
- w = x.parent.right
- if w.color == Node::RED
- w.color = Node::BLACK
- x.parent.color = Node::RED
- left_rotate(x.parent)
- w = x.parent.right
- end
- if w.left.color == Node::BLACK && w.right.color == Node::BLACK
- w.color = Node::RED
- x = x.parent
- else
- if w.right.color == Node::BLACK
- w.left.color = Node::BLACK
- w.color = Node::RED
- right_rotate(w)
- w = x.parent.right
- end
- w.color = x.parent.color
- x.parent.color = Node::BLACK
- w.right.color = Node::BLACK
- left_rotate(x.parent)
- x = root
- end
- else
- w = x.parent.left
- if w.color == Node::RED
- w.color = Node::BLACK
- x.parent.color = Node::RED
- right_rotate(x.parent)
- w = x.parent.left
- end
- if w.right.color == Node::BLACK && w.left.color == Node::BLACK
- w.color = Node::RED
- x = x.parent
- else
- if w.left.color == Node::BLACK
- w.right.color = Node::BLACK
- w.color = Node::RED
- left_rotate(w)
- w = x.parent.left
- end
- w.color = x.parent.color
- x.parent.color = Node::BLACK
- w.left.color = Node::BLACK
- right_rotate(x.parent)
- x = root
- end
- end
- end
- x.color = Node::BLACK
- end
-end
+# Algorithm based on "Introduction to Algorithms" by Cormen and others
+class RedBlackTree
+ class Node
+ attr_accessor :color
+ attr_accessor :key
+ attr_accessor :left
+ attr_accessor :right
+ attr_accessor :parent
+
+ RED = :red
+ BLACK = :black
+ COLORS = [RED, BLACK].freeze
+
+ def initialize(key, color = RED)
+ raise ArgumentError, "Bad value for color parameter" unless COLORS.include?(color)
+ @color = color
+ @key = key
+ @left = @right = @parent = NilNode.instance
+ end
+
+ def black?
+ return color == BLACK
+ end
+
+ def red?
+ return color == RED
+ end
+ end
+
+ class NilNode < Node
+ class << self
+ private :new
+ @instance = nil
+
+ # it's not thread safe
+ def instance
+ if @instance.nil?
+ @instance = new
+
+ def instance
+ return @instance
+ end
+ end
+
+ return @instance
+ end
+ end
+
+ def initialize
+ self.color = BLACK
+ self.key = 0
+ self.left = nil
+ self.right = nil
+ self.parent = nil
+ end
+
+ def nil?
+ return true
+ end
+ end
+
+ include Enumerable
+
+ attr_accessor :root
+ attr_accessor :size
+
+ def initialize
+ self.root = NilNode.instance
+ self.size = 0
+ end
+
+ def add(key)
+ insert(Node.new(key))
+ end
+
+ def insert(x)
+ insert_helper(x)
+
+ x.color = Node::RED
+ while x != root && x.parent.color == Node::RED
+ if x.parent == x.parent.parent.left
+ y = x.parent.parent.right
+ if !y.nil? && y.color == Node::RED
+ x.parent.color = Node::BLACK
+ y.color = Node::BLACK
+ x.parent.parent.color = Node::RED
+ x = x.parent.parent
+ else
+ if x == x.parent.right
+ x = x.parent
+ left_rotate(x)
+ end
+ x.parent.color = Node::BLACK
+ x.parent.parent.color = Node::RED
+ right_rotate(x.parent.parent)
+ end
+ else
+ y = x.parent.parent.left
+ if !y.nil? && y.color == Node::RED
+ x.parent.color = Node::BLACK
+ y.color = Node::BLACK
+ x.parent.parent.color = Node::RED
+ x = x.parent.parent
+ else
+ if x == x.parent.left
+ x = x.parent
+ right_rotate(x)
+ end
+ x.parent.color = Node::BLACK
+ x.parent.parent.color = Node::RED
+ left_rotate(x.parent.parent)
+ end
+ end
+ end
+ root.color = Node::BLACK
+ end
+
+ alias << insert
+
+ def delete(z)
+ y = (z.left.nil? || z.right.nil?) ? z : successor(z)
+ x = y.left.nil? ? y.right : y.left
+ x.parent = y.parent
+
+ if y.parent.nil?
+ self.root = x
+ else
+ if y == y.parent.left
+ y.parent.left = x
+ else
+ y.parent.right = x
+ end
+ end
+
+ z.key = y.key if y != z
+
+ if y.color == Node::BLACK
+ delete_fixup(x)
+ end
+
+ self.size -= 1
+ return y
+ end
+
+ def minimum(x = root)
+ while !x.left.nil?
+ x = x.left
+ end
+ return x
+ end
+
+ def maximum(x = root)
+ while !x.right.nil?
+ x = x.right
+ end
+ return x
+ end
+
+ def successor(x)
+ if !x.right.nil?
+ return minimum(x.right)
+ end
+ y = x.parent
+ while !y.nil? && x == y.right
+ x = y
+ y = y.parent
+ end
+ return y
+ end
+
+ def predecessor(x)
+ if !x.left.nil?
+ return maximum(x.left)
+ end
+ y = x.parent
+ while !y.nil? && x == y.left
+ x = y
+ y = y.parent
+ end
+ return y
+ end
+
+ def inorder_walk(x = root)
+ x = self.minimum
+ while !x.nil?
+ yield x.key
+ x = successor(x)
+ end
+ end
+
+ alias each inorder_walk
+
+ def reverse_inorder_walk(x = root)
+ x = self.maximum
+ while !x.nil?
+ yield x.key
+ x = predecessor(x)
+ end
+ end
+
+ alias reverse_each reverse_inorder_walk
+
+ def search(key, x = root)
+ while !x.nil? && x.key != key
+ key < x.key ? x = x.left : x = x.right
+ end
+ return x
+ end
+
+ def empty?
+ return self.root.nil?
+ end
+
+ def black_height(x = root)
+ height = 0
+ while !x.nil?
+ x = x.left
+ height +=1 if x.nil? || x.black?
+ end
+ return height
+ end
+
+private
+
+ def left_rotate(x)
+ raise "x.right is nil!" if x.right.nil?
+ y = x.right
+ x.right = y.left
+ y.left.parent = x if !y.left.nil?
+ y.parent = x.parent
+ if x.parent.nil?
+ self.root = y
+ else
+ if x == x.parent.left
+ x.parent.left = y
+ else
+ x.parent.right = y
+ end
+ end
+ y.left = x
+ x.parent = y
+ end
+
+ def right_rotate(x)
+ raise "x.left is nil!" if x.left.nil?
+ y = x.left
+ x.left = y.right
+ y.right.parent = x if !y.right.nil?
+ y.parent = x.parent
+ if x.parent.nil?
+ self.root = y
+ else
+ if x == x.parent.left
+ x.parent.left = y
+ else
+ x.parent.right = y
+ end
+ end
+ y.right = x
+ x.parent = y
+ end
+
+ def insert_helper(z)
+ y = NilNode.instance
+ x = root
+ while !x.nil?
+ y = x
+ z.key < x.key ? x = x.left : x = x.right
+ end
+ z.parent = y
+ if y.nil?
+ self.root = z
+ else
+ z.key < y.key ? y.left = z : y.right = z
+ end
+ self.size += 1
+ end
+
+ def delete_fixup(x)
+ while x != root && x.color == Node::BLACK
+ if x == x.parent.left
+ w = x.parent.right
+ if w.color == Node::RED
+ w.color = Node::BLACK
+ x.parent.color = Node::RED
+ left_rotate(x.parent)
+ w = x.parent.right
+ end
+ if w.left.color == Node::BLACK && w.right.color == Node::BLACK
+ w.color = Node::RED
+ x = x.parent
+ else
+ if w.right.color == Node::BLACK
+ w.left.color = Node::BLACK
+ w.color = Node::RED
+ right_rotate(w)
+ w = x.parent.right
+ end
+ w.color = x.parent.color
+ x.parent.color = Node::BLACK
+ w.right.color = Node::BLACK
+ left_rotate(x.parent)
+ x = root
+ end
+ else
+ w = x.parent.left
+ if w.color == Node::RED
+ w.color = Node::BLACK
+ x.parent.color = Node::RED
+ right_rotate(x.parent)
+ w = x.parent.left
+ end
+ if w.right.color == Node::BLACK && w.left.color == Node::BLACK
+ w.color = Node::RED
+ x = x.parent
+ else
+ if w.left.color == Node::BLACK
+ w.right.color = Node::BLACK
+ w.color = Node::RED
+ left_rotate(w)
+ w = x.parent.left
+ end
+ w.color = x.parent.color
+ x.parent.color = Node::BLACK
+ w.left.color = Node::BLACK
+ right_rotate(x.parent)
+ x = root
+ end
+ end
+ end
+ x.color = Node::BLACK
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.