ds 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
-