ds 0.0.4 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +11 -0
  3. data/.rubocop_todo.yml +452 -0
  4. data/.travis.yml +12 -0
  5. data/Gemfile +1 -1
  6. data/README.rdoc +185 -214
  7. data/Rakefile +8 -3
  8. data/ds.gemspec +16 -13
  9. data/lib/ds.rb +20 -30
  10. data/lib/ds/{matrixes → arrays}/array_2d.rb +9 -10
  11. data/lib/ds/arrays/expandable_array.rb +34 -0
  12. data/lib/ds/arrays/heap_store.rb +32 -0
  13. data/lib/ds/arrays/tri_matrix.rb +33 -0
  14. data/lib/ds/lists/list.rb +310 -186
  15. data/lib/ds/lists/list_element.rb +14 -11
  16. data/lib/ds/pair.rb +4 -4
  17. data/lib/ds/queues/priority_queue.rb +33 -20
  18. data/lib/ds/queues/simple_queue.rb +55 -0
  19. data/lib/ds/sets/indexed_set.rb +37 -0
  20. data/lib/ds/stacks/stack.rb +25 -17
  21. data/lib/ds/trees/binary_heap.rb +71 -66
  22. data/lib/ds/trees/binary_tree.rb +40 -44
  23. data/lib/ds/trees/red_black_tree.rb +123 -0
  24. data/lib/ds/trees/red_black_tree/node.rb +21 -0
  25. data/lib/ds/trees/tree.rb +50 -48
  26. data/lib/ds/trees/tree_walker.rb +73 -144
  27. data/lib/ds/trees/trie.rb +67 -37
  28. data/lib/ds/trees/trie/node.rb +48 -0
  29. data/lib/ds/version.rb +2 -1
  30. data/test/help.rb +3 -6
  31. data/test/performance/binary_heap_performance_test.rb +20 -0
  32. data/test/performance/list_performance_test.rb +36 -0
  33. data/test/performance/priority_queue_performance.rb +32 -0
  34. data/test/performance/rbt_performance_test.rb +17 -0
  35. data/test/performance/simple_queue_performance_test.rb +37 -0
  36. data/test/performance/stack_test.rb +45 -0
  37. data/test/test_array2d.rb +29 -31
  38. data/test/test_binary_heap.rb +29 -23
  39. data/test/test_binary_tree.rb +30 -20
  40. data/test/test_expandable_array.rb +6 -10
  41. data/test/test_heap_store.rb +34 -0
  42. data/test/test_indexed_set.rb +26 -0
  43. data/test/test_list.rb +226 -109
  44. data/test/test_list_element.rb +34 -16
  45. data/test/test_pair.rb +5 -8
  46. data/test/test_priority_queue.rb +43 -64
  47. data/test/test_queue.rb +12 -61
  48. data/test/test_red_black_tree.rb +46 -0
  49. data/test/test_stack.rb +35 -39
  50. data/test/test_tree.rb +42 -29
  51. data/test/test_tree_walker.rb +27 -52
  52. data/test/test_tri_matrix.rb +6 -11
  53. data/test/test_trie.rb +59 -17
  54. metadata +80 -35
  55. data/lib/ds/ext/array_x.rb +0 -35
  56. data/lib/ds/graphs/digraph.rb +0 -20
  57. data/lib/ds/graphs/edge.rb +0 -15
  58. data/lib/ds/graphs/graph.rb +0 -111
  59. data/lib/ds/graphs/graph_as_matrix.rb +0 -113
  60. data/lib/ds/graphs/graph_as_tri_matrix.rb +0 -24
  61. data/lib/ds/lists/cyclic_list.rb +0 -21
  62. data/lib/ds/lists/ring.rb +0 -42
  63. data/lib/ds/matrixes/expandable_array.rb +0 -37
  64. data/lib/ds/matrixes/tri_matrix.rb +0 -30
  65. data/lib/ds/queues/queue.rb +0 -53
  66. data/lib/ds/sets/ordered_set.rb +0 -32
  67. data/lib/ds/trees/binary_search_tree.rb +0 -34
  68. data/lib/ds/trees/complete_binary_tree.rb +0 -60
  69. data/test/test_array_x.rb +0 -51
  70. data/test/test_binary_search_tree.rb +0 -39
  71. data/test/test_complete_binary_tree.rb +0 -58
  72. data/test/test_digraph.rb +0 -134
  73. data/test/test_graph.rb +0 -80
  74. data/test/test_ordered_set.rb +0 -28
  75. data/test/test_ring.rb +0 -28
@@ -1,71 +1,67 @@
1
1
  module DS
2
+ # Class implements binary tree
2
3
  class BinaryTree < Tree
3
-
4
- #Inserts a new subtree.
5
- def << (value)
6
- subtree = BinaryTree.new(value)
4
+ # Inserts a new subtree.
5
+ def <<(value)
6
+ subtree = BinaryTree.new(value, self)
7
7
  @children << subtree
8
- return subtree
8
+ subtree
9
9
  end
10
10
 
11
- #Returns left subtree
11
+ # Returns left subtree
12
12
  def left
13
- if @children.empty?
14
- nil
15
- else
16
- @children[0]
17
- end
13
+ @children[0]
18
14
  end
19
15
 
20
- #Sets left subtree
16
+ # Sets left subtree
21
17
  def left=(value)
22
18
  @children[0] = value
23
19
  end
24
20
 
25
- #Returns right subtree
21
+ # Returns right subtree
26
22
  def right
27
- if @children.empty?
28
- nil
29
- else
30
- @children[1]
31
- end
23
+ @children[1]
32
24
  end
33
25
 
34
- #Sets right subtree
26
+ # Sets right subtree
35
27
  def right=(value)
36
28
  @children[1] = value
37
29
  end
38
30
 
39
-
40
- #Inserts new element in BSF order
31
+ # Inserts new element in BSF order
41
32
  def insert(x)
42
- q = Queue.new
43
- if @data == nil
33
+ q = SimpleQueue.new
34
+ if @data.nil?
44
35
  @data = x
45
- elsif self.left == nil
46
- self.left = BinaryTree.new(x)
47
- elsif self.right == nil
48
- self.right = BinaryTree.new(x)
36
+ elsif left.nil?
37
+ self.left = BinaryTree.new(x, self)
38
+ elsif right.nil?
39
+ self.right = BinaryTree.new(x, self)
49
40
  else
50
- q.push self.left
51
- q.push self.right
52
- loop do
53
- node = q.shift
54
- if node.left == nil
55
- node.insert(x)
56
- break
57
- else
58
- q.push node.left
59
- end
60
- if node.right == nil
61
- node.insert(x)
62
- break
63
- else
64
- q.push node.right
65
- end
41
+ q.push left
42
+ q.push right
43
+ insert_next(q, x)
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def insert_next(q, x)
50
+ loop do
51
+ node = q.shift
52
+ if node.left.nil?
53
+ node.insert(x)
54
+ break
55
+ else
56
+ q.push node.left
57
+ end
58
+ if node.right.nil?
59
+ node.insert(x)
60
+ break
61
+ else
62
+ q.push node.right
66
63
  end
67
64
  end
68
65
  end
69
66
  end
70
67
  end
71
-
@@ -0,0 +1,123 @@
1
+ module DS
2
+ # Class implements Red Black Tree
3
+ class RedBlackTree
4
+ RED = true
5
+ BLACK = false
6
+
7
+ include Enumerable
8
+
9
+ attr_accessor :root
10
+ attr_reader :size
11
+
12
+ def initialize(hash = nil)
13
+ @root = nil
14
+ @size = 0
15
+ @iterator = TreeWalker.new(root)
16
+ hash.each { |k, v| insert(k, v) } if hash
17
+ end
18
+
19
+ def insert(key, value)
20
+ self.root = put(root, key, value)
21
+ root.color = BLACK
22
+ end
23
+
24
+ def []=(key, value)
25
+ insert(key, value)
26
+ end
27
+
28
+ def get(key, node = root)
29
+ x = node
30
+ while x
31
+ case key <=> x.key
32
+ when -1
33
+ x = x.left
34
+ when 1
35
+ x = x.right
36
+ else
37
+ return x.data
38
+ end
39
+ end
40
+ end
41
+
42
+ def [](key)
43
+ get(key)
44
+ end
45
+
46
+ def each
47
+ iterator = TreeWalker.new(root)
48
+ iterator.traverse(:inorder) { |t| yield t }
49
+ end
50
+
51
+ def to_h
52
+ each_with_object({}) { |n, h| h[n.key] = n.data }
53
+ end
54
+
55
+ private
56
+
57
+ def put(n, key, value)
58
+ if n.nil?
59
+ @size += 1
60
+ return Node.new(key, value, RED)
61
+ end
62
+
63
+ case key <=> n.key
64
+ when -1
65
+ n.left = put(n.left, key, value)
66
+ when 1
67
+ n.right = put(n.right, key, value)
68
+ else
69
+ n.data = value
70
+ end
71
+
72
+ balance(n)
73
+ end
74
+
75
+ def balance(n)
76
+ n = rotate_left(n) if right_red?(n)
77
+ n = rotate_right(n) if two_red_in_row?(n)
78
+ flip_colors(n) if red_children?(n)
79
+ n
80
+ end
81
+
82
+ def red_children?(n)
83
+ red?(n.left) && red?(n.right)
84
+ end
85
+
86
+ def two_red_in_row?(n)
87
+ red?(n.left) && red?(n.left.left)
88
+ end
89
+
90
+ def right_red?(n)
91
+ red?(n.right) && !red?(n.left)
92
+ end
93
+
94
+ def red?(n)
95
+ return false if n.nil?
96
+ n.color == RED
97
+ end
98
+
99
+ def rotate_left(n)
100
+ x = n.right
101
+ n.right = x.left
102
+ x.left = n
103
+ x.color = n.color
104
+ n.color = RED
105
+ x
106
+ end
107
+
108
+ def rotate_right(n)
109
+ x = n.left
110
+ n.left = x.right
111
+ x.right = n
112
+ x.color = n.color
113
+ n.color = RED
114
+ x
115
+ end
116
+
117
+ def flip_colors(n)
118
+ n.color = RED
119
+ n.left.color = BLACK
120
+ n.right.color = BLACK
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,21 @@
1
+ module DS
2
+ # Class implements Red Black Tree
3
+ class RedBlackTree
4
+ # Red Black Tree Node
5
+ class Node
6
+ attr_accessor :color, :right, :left, :data, :key
7
+
8
+ def initialize(key, value, color)
9
+ @key = key
10
+ @data = value
11
+ @color = color
12
+ @left = nil
13
+ @right = nil
14
+ end
15
+
16
+ def children
17
+ [@left, @right]
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,55 +1,59 @@
1
1
  module DS
2
+ # Tree class
2
3
  class Tree
3
-
4
4
  include Enumerable
5
5
 
6
6
  attr_accessor :data
7
- attr_reader :children
7
+ attr_reader :children, :parent
8
8
 
9
- #Returns a new tree.
10
- def initialize(value=nil)
9
+ # Returns a new tree.
10
+ def initialize(value = nil, parent = nil)
11
11
  @data = value
12
+ @parent = parent
12
13
  @children = []
13
14
  end
14
15
 
15
- #Inserts a new subtree.
16
- def << (value)
17
- subtree = Tree.new(value)
16
+ # Inserts a new subtree.
17
+ def <<(value)
18
+ subtree = Tree.new(value, self)
18
19
  @children << subtree
19
- return subtree
20
+ subtree
21
+ end
22
+
23
+ def sibblings
24
+ parent.children.reject { |node| node == self }
20
25
  end
21
26
 
22
- #Checks if node is leaf.
27
+ # Checks if node is leaf.
23
28
  def leaf?
24
- self.children.empty?
29
+ children.empty?
25
30
  end
26
31
 
27
- #Returns leaf list.
28
- def get_leaves(tree=self)
32
+ # Returns leaf list.
33
+ def get_leaves(tree = self)
29
34
  list = List.new
30
- walker = TreeWalker.new(self)
31
- walker.traverse(:postorder){|t| list.append(t) if t.leaf? }
35
+ walker = TreeWalker.new(tree, order: :postorder)
36
+ walker.traverse { |t| list.append(t) if t.leaf? }
32
37
  list
33
38
  end
34
39
 
35
- #Returns the number of leaves for given subtree.
36
- def leaf_count(tree=self)
40
+ # Returns the number of leaves for given subtree.
41
+ def leaf_count(tree = self)
37
42
  if tree.leaf?
38
43
  1
39
44
  else
40
- tree.children.inject(0){|m,t| m += leaf_count(t)}
45
+ tree.children.inject(0) { |a, e| a + leaf_count(e) }
41
46
  end
42
47
  end
43
48
 
44
-
45
- #Returns number of nodes for each tree level.
46
- #{1=>1, 2=>4, 3=>5}
49
+ # Returns number of nodes for each tree level.
50
+ # {1=>1, 2=>4, 3=>5}
47
51
  def levels
48
52
  walker = TreeWalker.new(self)
49
- nodes={}
53
+ nodes = {}
50
54
 
51
- walker.traverse_with_h(self,1) do |t,level|
52
- if nodes[level]
55
+ walker.traverse_with_h(self, 1) do |_t, level|
56
+ if nodes[level]
53
57
  nodes[level] += 1
54
58
  else
55
59
  nodes[level] = 1
@@ -58,60 +62,58 @@ module DS
58
62
  nodes
59
63
  end
60
64
 
61
- #Returns tree width.
65
+ # Returns tree width.
62
66
  def width
63
- levels.values.max
67
+ levels.values.max
64
68
  end
65
-
66
- #Returns subtree height.
69
+
70
+ # Returns subtree height.
67
71
  def self.h(tree)
68
- unless tree.leaf?
69
- tree.children.map{|t| h(t) }.max + 1
70
- else
72
+ if tree.leaf?
71
73
  1
74
+ else
75
+ tree.children.map { |t| h(t) }.max + 1
72
76
  end
73
77
  end
74
78
 
75
- #Returns tree height.
79
+ # Returns tree height.
76
80
  def height
77
81
  Tree.h(self)
78
82
  end
79
83
 
80
- #Returns node which lies closest to the root.
84
+ # Returns node which lies closest to the root.
81
85
  def lowest_height
82
- find{ |node| node.leaf? }
86
+ find(&:leaf?)
83
87
  end
84
88
 
85
- #Mirrors tree.
86
- def mirror!(tree=self)
87
- unless tree.leaf?
88
- tree.children.reverse!
89
- tree.children.each{|t| mirror!(t)}
90
- end
89
+ # Mirrors tree.
90
+ def mirror!(tree = self)
91
+ return if tree.leaf?
92
+ tree.children.reverse!
93
+ tree.children.each { |t| mirror!(t) }
91
94
  end
92
95
 
93
- #Checks if tree is isometric to another tree.
96
+ # Checks if tree is isometric to another tree.
94
97
  def izometric?(other)
95
98
  tree = self
96
- unless tree.leaf? and other.leaf?
99
+ unless tree.leaf? && other.leaf?
97
100
  if tree.children.size == other.children.size
98
- tree.children.each_with_index{|t,i| return false unless t.izometric?(other.children[i])}
101
+ tree.children.each_with_index { |t, i| return false unless t.izometric?(other.children[i]) }
99
102
  else
100
103
  return false
101
104
  end
102
105
  end
103
- return true
106
+ true
104
107
  end
105
108
 
106
-
107
- #Iterates tree in BFS order.
109
+ # Iterates tree in BFS order.
108
110
  def each
109
- TreeWalker.new(self).traverse{ |t| yield t }
111
+ iterator = TreeWalker.new(self)
112
+ iterator.traverse { |t| yield t }
110
113
  end
111
114
 
112
115
  def to_a
113
- map{ |node| node.data }
116
+ map(&:data)
114
117
  end
115
118
  end
116
119
  end
117
-
@@ -1,180 +1,109 @@
1
1
  module DS
2
+ # Tree enumerator
2
3
  class TreeWalker
4
+ attr_accessor :visited, :tree, :action, :order
3
5
 
4
- attr_accessor :visited
5
- attr_accessor :tree
6
-
7
-
8
- #Creates new tree iterator.
9
- def initialize(tree=nil)
10
- @visited = []
6
+ # Creates new tree iterator.
7
+ def initialize(tree, options = {}, &block)
8
+ @visited = []
11
9
  @tree = tree
10
+ @order = options[:order] || :bfs
11
+ @action = block
12
12
  end
13
13
 
14
-
15
- #Traversing tree in given order:
16
- #bfs - Breadth-first search - default
17
- #postorder - postorder search
18
- #preorder - preorder search
19
- #inorder - inorder search - only for Binary Trees
14
+ # Traversing tree in given order:
15
+ # bfs - Breadth-first search - default
16
+ # postorder - postorder search
17
+ # preorder - preorder search
18
+ # inorder - inorder search - only for Binary Trees
20
19
  #
21
- #If block is given, passes each visited subtree to block.
22
- #Returns values of nodes in given order
23
-
24
- def traverse(order=:bfs,&block)
25
- reset
26
- tree = @tree
27
-
28
- case order
29
- when :bfs
30
- traverse_bfs &block
31
- when :postorder
32
- walk(tree,:postorder,&block)
33
- when :preorder
34
- walk(tree,:preorder, &block)
35
- when :inorder
36
- raise ArgumentError unless tree.kind_of? BinaryTree
37
- walk(tree,order,&block)
20
+ # If block is given, passes each visited subtree to block.
21
+ # Returns values of nodes in given order
22
+
23
+ def traverse(traverse_order = nil, &block)
24
+ self.action = block if block_given?
25
+ self.order = traverse_order if traverse_order
26
+ reset!
27
+
28
+ if order == :bfs
29
+ traverse_bfs
30
+ else
31
+ walk(tree)
38
32
  end
39
-
40
- return visited
33
+ visited
41
34
  end
42
35
 
43
- #Traverses tree in BFS order.
44
- def traverse_bfs
45
- q = Queue.new
46
- q.push @tree
47
-
36
+ # Traverses tree in BFS order.
37
+ def traverse_bfs(&block)
38
+ self.action = block if block_given?
39
+ q = SimpleQueue.new
40
+ q.push tree
41
+
48
42
  loop do
49
43
  break if q.empty?
50
44
  node = q.shift
51
- if block_given?
52
- yield node
53
- else
54
- @visited << node.data
55
- end
56
- node.children.each{ |n| q.push n } if node.children
45
+ visit_node(node)
46
+ node.children.each { |n| q.push n } if node.children
57
47
  end
58
48
  end
59
49
 
60
- #Resets tree walker.
61
- def reset
50
+ # Resets tree walker.
51
+ def reset!
62
52
  @visited.clear
63
53
  self
64
54
  end
65
55
 
66
-
67
-
68
- #Traverses tree with tracking level.
69
- def traverse_with_h(tree,height=nil,&block)
70
-
56
+ # Traverses tree with tracking level.
57
+ def traverse_with_h(tree, height = nil, &block)
71
58
  tree.children.each do |t|
72
- traverse_with_h(t,height+1,&block)
73
- end
74
-
75
- if block_given?
76
- yield tree, height
59
+ traverse_with_h(t, height + 1, &block)
77
60
  end
78
61
 
62
+ yield tree, height if block_given?
79
63
  end
80
64
 
81
-
82
- #Recalculates tree by evaluating block on every node.
83
- def recalculate!(tree,order,memo=nil,&block)
84
- if tree
85
-
86
- case order
87
- when :postorder
88
-
89
- arr = tree.children.map{ |t| recalculate!(t,order,memo,&block) }
90
- result = block.call(arr.push tree.data)
91
- tree.data = result
92
-
93
-
94
- when :preorder
95
-
96
- tree.data = yield tree, memo
97
- memo = tree.data
98
-
99
- tree.children.each do |t|
100
- recalculate!(t,order,memo,&block)
101
- end
102
-
103
- when :inorder
104
- raise ArgumentError unless self.tree.is_a? BinaryTree
105
- recalculate!(tree.left,order,memo,&block)
106
-
107
- tree.data = yield tree, memo
108
- memo = tree.data
109
-
110
- recalculate!(tree.right,order,memo,&block)
111
-
65
+ # Recalculates tree by evaluating block on every node.
66
+ def recalculate!(tree, order, memo = nil, &block)
67
+ case order
68
+ when :postorder
69
+ arr = tree.children.map { |t| recalculate!(t, order, memo, &block) }
70
+ tree.data = yield tree, arr
71
+ when :preorder
72
+ tree.data = yield tree, memo
73
+ tree.children.each do |t|
74
+ recalculate!(t, order, tree.data, &block)
112
75
  end
113
- end
114
- end
115
-
116
-
117
- #Summarize tree
118
- def summarize(direction=:bottomup)
119
-
120
- case direction
121
- when :bottomup
122
- recalculate!(self.tree,:postorder,0){|ar| ar.inject(0){|x,memo| memo += x}}
123
- self.tree
124
- when :topdown
125
- recalculate!(self.tree,:preorder,0){|x,memo| memo = memo+x.data}
126
- self.tree
127
76
  when :inorder
128
- recalculate!(self.tree,:inorder,0){|x,memo| memo = memo+x.data if x.data and memo}
129
- self.tree
130
- end
77
+ recalculate!(tree.left, order, memo, &block)
78
+ tree.data = yield tree, memo
79
+ recalculate!(tree.right, order, tree.data, &block)
80
+ end if tree
131
81
  end
132
82
 
133
-
134
-
135
83
  private
136
84
 
137
- def walk(tree,order,&block)
138
- if tree
139
-
140
- case order
141
- when :postorder
142
- tree.children.each do |t|
143
- walk(t,order,&block)
144
- end
145
-
146
- if block_given?
147
- yield tree
148
- else
149
- @visited << tree.data
150
- end
151
-
152
- when :preorder
153
- if block_given?
154
- yield tree
155
- else
156
- @visited << tree.data
157
- end
158
-
159
- tree.children.each do |t|
160
- walk(t,order,&block)
161
- end
162
-
163
- when :inorder
164
- raise ArgumentError unless self.tree.is_a? BinaryTree
165
- walk(tree.left,order,&block)
166
-
167
- if block_given?
168
- yield tree
169
- else
170
- @visited << tree.data
171
- end
85
+ def visit_node(node)
86
+ action.call(node) if action
87
+ @visited << node.data
88
+ end
172
89
 
173
- walk(tree.right,order,&block)
90
+ def visit_children(node)
91
+ node.children.each { |t| walk(t) }
92
+ end
174
93
 
175
- end
176
- end
94
+ def walk(node)
95
+ case order
96
+ when :postorder
97
+ visit_children(node)
98
+ visit_node(node)
99
+ when :preorder
100
+ visit_node(node)
101
+ visit_children(node)
102
+ when :inorder
103
+ walk(node.left)
104
+ visit_node(node)
105
+ walk(node.right)
106
+ end if node
177
107
  end
178
108
  end
179
109
  end
180
-