ds 0.0.1
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.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +13 -0
- data/doc/Array.html +264 -0
- data/doc/DS.html +292 -0
- data/doc/DS/Array2D.html +345 -0
- data/doc/DS/BinaryHeap.html +493 -0
- data/doc/DS/BinarySearchTree.html +313 -0
- data/doc/DS/BinaryTree.html +433 -0
- data/doc/DS/CompleteBinaryTree.html +550 -0
- data/doc/DS/CyclicList.html +234 -0
- data/doc/DS/Digraph.html +299 -0
- data/doc/DS/Edge.html +283 -0
- data/doc/DS/ExpandableArray.html +316 -0
- data/doc/DS/Graph.html +739 -0
- data/doc/DS/GraphAsList.html +361 -0
- data/doc/DS/GraphAsMatrix.html +633 -0
- data/doc/DS/GraphAsTriMatrix.html +274 -0
- data/doc/DS/List.html +1263 -0
- data/doc/DS/ListElement.html +344 -0
- data/doc/DS/Queue.html +517 -0
- data/doc/DS/Ring.html +323 -0
- data/doc/DS/Stack.html +407 -0
- data/doc/DS/Tree.html +770 -0
- data/doc/DS/TreeWalker.html +561 -0
- data/doc/DS/TriMatrix.html +338 -0
- data/doc/created.rid +25 -0
- data/doc/ds/graphs/digraph_rb.html +52 -0
- data/doc/ds/graphs/edge_rb.html +52 -0
- data/doc/ds/graphs/graph_as_list_rb.html +52 -0
- data/doc/ds/graphs/graph_as_matrix_rb.html +52 -0
- data/doc/ds/graphs/graph_as_tri_matrix_rb.html +52 -0
- data/doc/ds/graphs/graph_rb.html +52 -0
- data/doc/ds/lists/cyclic_list_rb.html +52 -0
- data/doc/ds/lists/list_element_rb.html +52 -0
- data/doc/ds/lists/list_rb.html +52 -0
- data/doc/ds/lists/ring_rb.html +52 -0
- data/doc/ds/matrixes/array_2d_rb.html +52 -0
- data/doc/ds/matrixes/expandable_array_rb.html +52 -0
- data/doc/ds/matrixes/tri_matrix_rb.html +52 -0
- data/doc/ds/queues/queue_rb.html +52 -0
- data/doc/ds/stacks/stack_rb.html +52 -0
- data/doc/ds/trees/binary_heap_rb.html +52 -0
- data/doc/ds/trees/binary_search_tree_rb.html +52 -0
- data/doc/ds/trees/binary_tree_rb.html +52 -0
- data/doc/ds/trees/complete_binary_tree_rb.html +52 -0
- data/doc/ds/trees/tree_rb.html +52 -0
- data/doc/ds/trees/tree_walker_rb.html +52 -0
- data/doc/ds/version_rb.html +52 -0
- data/doc/ds_rb.html +98 -0
- data/doc/ext/ext_rb.html +52 -0
- data/doc/images/brick.png +0 -0
- data/doc/images/brick_link.png +0 -0
- data/doc/images/bug.png +0 -0
- data/doc/images/bullet_black.png +0 -0
- data/doc/images/bullet_toggle_minus.png +0 -0
- data/doc/images/bullet_toggle_plus.png +0 -0
- data/doc/images/date.png +0 -0
- data/doc/images/find.png +0 -0
- data/doc/images/loadingAnimation.gif +0 -0
- data/doc/images/macFFBgHack.png +0 -0
- data/doc/images/package.png +0 -0
- data/doc/images/page_green.png +0 -0
- data/doc/images/page_white_text.png +0 -0
- data/doc/images/page_white_width.png +0 -0
- data/doc/images/plugin.png +0 -0
- data/doc/images/ruby.png +0 -0
- data/doc/images/tag_green.png +0 -0
- data/doc/images/wrench.png +0 -0
- data/doc/images/wrench_orange.png +0 -0
- data/doc/images/zoom.png +0 -0
- data/doc/index.html +375 -0
- data/doc/js/darkfish.js +116 -0
- data/doc/js/jquery.js +32 -0
- data/doc/js/quicksearch.js +114 -0
- data/doc/js/thickbox-compressed.js +10 -0
- data/doc/rdoc.css +763 -0
- data/ds.gemspec +20 -0
- data/lib/ds.rb +38 -0
- data/lib/ds/graphs/digraph.rb +20 -0
- data/lib/ds/graphs/edge.rb +15 -0
- data/lib/ds/graphs/graph.rb +107 -0
- data/lib/ds/graphs/graph_as_list.rb +48 -0
- data/lib/ds/graphs/graph_as_matrix.rb +114 -0
- data/lib/ds/graphs/graph_as_tri_matrix.rb +25 -0
- data/lib/ds/lists/cyclic_list.rb +21 -0
- data/lib/ds/lists/list.rb +303 -0
- data/lib/ds/lists/list_element.rb +26 -0
- data/lib/ds/lists/ring.rb +42 -0
- data/lib/ds/matrixes/array_2d.rb +35 -0
- data/lib/ds/matrixes/expandable_array.rb +37 -0
- data/lib/ds/matrixes/tri_matrix.rb +30 -0
- data/lib/ds/queues/queue.rb +53 -0
- data/lib/ds/stacks/stack.rb +39 -0
- data/lib/ds/trees/binary_heap.rb +71 -0
- data/lib/ds/trees/binary_search_tree.rb +32 -0
- data/lib/ds/trees/binary_tree.rb +65 -0
- data/lib/ds/trees/complete_binary_tree.rb +52 -0
- data/lib/ds/trees/tree.rb +117 -0
- data/lib/ds/trees/tree_walker.rb +179 -0
- data/lib/ds/version.rb +3 -0
- data/lib/ext/ext.rb +15 -0
- data/test/help.rb +8 -0
- data/test/test_array2d.rb +51 -0
- data/test/test_binary_heap.rb +35 -0
- data/test/test_binary_search_tree.rb +32 -0
- data/test/test_binary_tree.rb +51 -0
- data/test/test_complete_binary_tree.rb +30 -0
- data/test/test_digraph.rb +134 -0
- data/test/test_expandable_array.rb +26 -0
- data/test/test_graph.rb +71 -0
- data/test/test_list.rb +138 -0
- data/test/test_list_element.rb +56 -0
- data/test/test_queue.rb +110 -0
- data/test/test_ring.rb +28 -0
- data/test/test_stack.rb +87 -0
- data/test/test_tree.rb +48 -0
- data/test/test_tree_walker.rb +69 -0
- data/test/test_tri_matrix.rb +22 -0
- metadata +184 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
module DS
|
|
2
|
+
class Tree
|
|
3
|
+
|
|
4
|
+
include Enumerable
|
|
5
|
+
|
|
6
|
+
attr_accessor :data
|
|
7
|
+
attr_reader :children
|
|
8
|
+
|
|
9
|
+
#Returns a new tree.
|
|
10
|
+
def initialize(value=nil)
|
|
11
|
+
@data = value
|
|
12
|
+
@children = []
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
#Inserts a new subtree.
|
|
16
|
+
def << (value)
|
|
17
|
+
subtree = Tree.new(value)
|
|
18
|
+
@children << subtree
|
|
19
|
+
return subtree
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
#Checks if node is leaf.
|
|
23
|
+
def leaf?
|
|
24
|
+
self.children.empty?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
#Returns leaf list.
|
|
28
|
+
def get_leaves(tree=self)
|
|
29
|
+
list = List.new
|
|
30
|
+
walker = TreeWalker.new(self)
|
|
31
|
+
walker.traverse(:postorder){|t| list.append(t) if t.leaf? }
|
|
32
|
+
list
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
#Returns the number of leaves for given subtree.
|
|
36
|
+
def leaf_count(tree=self)
|
|
37
|
+
if tree.leaf?
|
|
38
|
+
1
|
|
39
|
+
else
|
|
40
|
+
tree.children.inject(0){|m,t| m += leaf_count(t)}
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
#Returns number of nodes for each tree level.
|
|
46
|
+
#{1=>1, 2=>4, 3=>5}
|
|
47
|
+
def levels
|
|
48
|
+
walker = TreeWalker.new(self)
|
|
49
|
+
nodes={}
|
|
50
|
+
|
|
51
|
+
walker.traverse_with_h(self,1) do |t,level|
|
|
52
|
+
if nodes[level]
|
|
53
|
+
nodes[level] += 1
|
|
54
|
+
else
|
|
55
|
+
nodes[level] = 1
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
nodes
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
#Returns tree width.
|
|
62
|
+
def width
|
|
63
|
+
levels.values.max
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
#Returns subtree height.
|
|
67
|
+
def h(tree)
|
|
68
|
+
unless tree.leaf?
|
|
69
|
+
tree.children.map{|t| h(t) }.max + 1
|
|
70
|
+
else
|
|
71
|
+
1
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
#Returns tree height.
|
|
76
|
+
def height
|
|
77
|
+
h(self)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
#Returns node which lies closest to the root.
|
|
81
|
+
def lowest_height
|
|
82
|
+
find{ |node| node.leaf? }.data
|
|
83
|
+
end
|
|
84
|
+
|
|
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
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
#Checks if tree is isometric to another tree.
|
|
94
|
+
def izometric?(other)
|
|
95
|
+
tree = self
|
|
96
|
+
unless tree.leaf? and other.leaf?
|
|
97
|
+
if tree.children.size == other.children.size
|
|
98
|
+
tree.children.each_with_index{|t,i| return false unless t.izometric?(other.children[i])}
|
|
99
|
+
else
|
|
100
|
+
return false
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
return true
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
#Iterates tree in BFS order.
|
|
108
|
+
def each
|
|
109
|
+
TreeWalker.new(self).traverse{ |t| yield t }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def to_a
|
|
113
|
+
map{ |node| node.data }
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
module DS
|
|
2
|
+
class TreeWalker
|
|
3
|
+
|
|
4
|
+
attr_accessor :visited
|
|
5
|
+
attr_accessor :tree
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
#Creates new tree iterator.
|
|
9
|
+
def initialize(tree=nil)
|
|
10
|
+
@visited = []
|
|
11
|
+
@tree = tree
|
|
12
|
+
end
|
|
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
|
|
20
|
+
#
|
|
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)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
return visited
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
#Traverses tree in BFS order.
|
|
44
|
+
def traverse_bfs
|
|
45
|
+
q = Queue.new
|
|
46
|
+
q.push @tree
|
|
47
|
+
|
|
48
|
+
loop do
|
|
49
|
+
break if q.empty?
|
|
50
|
+
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
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
#Resets tree walker.
|
|
61
|
+
def reset
|
|
62
|
+
@visited.clear
|
|
63
|
+
self
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def traverse_with_h(tree,height=nil,&block)
|
|
69
|
+
|
|
70
|
+
tree.children.each do |t|
|
|
71
|
+
traverse_with_h(t,height+1,&block)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
if block_given?
|
|
75
|
+
yield tree, height
|
|
76
|
+
else
|
|
77
|
+
@visited << tree.data
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
#Recalculates tree by evaluating block on every node.
|
|
84
|
+
def recalculate!(tree,order,memo=nil,&block)
|
|
85
|
+
if tree
|
|
86
|
+
|
|
87
|
+
case order
|
|
88
|
+
when :postorder
|
|
89
|
+
|
|
90
|
+
arr = tree.children.map{ |t| recalculate!(t,order,memo,&block) }
|
|
91
|
+
result = block.call(arr.push tree.data)
|
|
92
|
+
tree.data = result
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
when :preorder
|
|
96
|
+
|
|
97
|
+
tree.data = yield tree, memo
|
|
98
|
+
memo = tree.data
|
|
99
|
+
|
|
100
|
+
tree.children.each do |t|
|
|
101
|
+
recalculate!(t,order,memo,&block)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
when :inorder
|
|
105
|
+
raise ArgumentError unless self.tree.is_a? BinaryTree
|
|
106
|
+
recalculate!(tree.left,order,&block)
|
|
107
|
+
|
|
108
|
+
tree.data = yield tree.memo
|
|
109
|
+
memo = tree.data
|
|
110
|
+
|
|
111
|
+
recalculate!(tree.right,order,memo,&block)
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
#Summarize tree
|
|
120
|
+
def summarize(direction=:bottomup)
|
|
121
|
+
|
|
122
|
+
case direction
|
|
123
|
+
when :bottomup
|
|
124
|
+
recalculate!(self.tree,:postorder,0){|ar| ar.inject(0){|x,memo| memo += x}}
|
|
125
|
+
self.tree
|
|
126
|
+
when :topdown
|
|
127
|
+
recalculate!(self.tree,:preorder,0){|x,memo| memo = memo+x.data}
|
|
128
|
+
self.tree
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
private
|
|
135
|
+
|
|
136
|
+
def walk(tree,order,&block)
|
|
137
|
+
if tree
|
|
138
|
+
|
|
139
|
+
case order
|
|
140
|
+
when :postorder
|
|
141
|
+
tree.children.each do |t|
|
|
142
|
+
walk(t,order,&block)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
if block_given?
|
|
146
|
+
yield tree
|
|
147
|
+
else
|
|
148
|
+
@visited << tree.data
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
when :preorder
|
|
152
|
+
if block_given?
|
|
153
|
+
yield tree
|
|
154
|
+
else
|
|
155
|
+
@visited << tree.data
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
tree.children.each do |t|
|
|
159
|
+
walk(t,order,&block)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
when :inorder
|
|
163
|
+
raise ArgumentError unless self.tree.is_a? BinaryTree
|
|
164
|
+
walk(tree.left,order,&block)
|
|
165
|
+
|
|
166
|
+
if block_given?
|
|
167
|
+
yield tree
|
|
168
|
+
else
|
|
169
|
+
@visited << tree.data
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
walk(tree.right,order,&block)
|
|
173
|
+
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
data/lib/ds/version.rb
ADDED
data/lib/ext/ext.rb
ADDED
data/test/help.rb
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'help'
|
|
2
|
+
|
|
3
|
+
describe Array2D do
|
|
4
|
+
|
|
5
|
+
describe "initialized with 0" do
|
|
6
|
+
|
|
7
|
+
before do
|
|
8
|
+
@zero_matrix = Array2D.new(2,0)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "should return zero for any index." do
|
|
12
|
+
@zero_matrix[1,1].must_equal 0
|
|
13
|
+
@zero_matrix[0,0].must_equal 0
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "#to_a should return matrix flattened to array." do
|
|
17
|
+
@zero_matrix.to_a.must_be_instance_of Array
|
|
18
|
+
@zero_matrix.to_a.must_equal [0,0,0,0]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "#should extend magically." do
|
|
22
|
+
@zero_matrix[3,3].must_equal 0
|
|
23
|
+
@zero_matrix[4,8].wont_be_nil
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "initialized with false" do
|
|
28
|
+
|
|
29
|
+
before do
|
|
30
|
+
@discrete_matrix = Array2D.new(3,false)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should return false for any index." do
|
|
34
|
+
refute @discrete_matrix[1,1]
|
|
35
|
+
refute @discrete_matrix[0,0]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "#to_a should return matrix flattened to array." do
|
|
39
|
+
@discrete_matrix.to_a.must_be_instance_of Array
|
|
40
|
+
@discrete_matrix.to_a.must_equal [false,false,false,false,false,false,false,false,false]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "#should extend magically." do
|
|
44
|
+
refute @discrete_matrix[3,3]
|
|
45
|
+
@discrete_matrix[4,8].wont_be_nil
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require "help"
|
|
2
|
+
|
|
3
|
+
describe BinaryHeap do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
@arr = [9,8,4,5,11,6]
|
|
7
|
+
@arr2 = [4,2,9,11,3,5,1]
|
|
8
|
+
@heap = BinaryHeap.new(*@arr)
|
|
9
|
+
@heap2 = BinaryHeap.new(*@arr2)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should create heap from array" do
|
|
13
|
+
@heap.to_a.must_equal [11,9,6,5,8,4]
|
|
14
|
+
@heap2.to_a.must_equal [11,4,9,2,3,5,1]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "#insert should insert new element to the heap maintaining heap relation." do
|
|
18
|
+
@heap.insert(13).to_a.must_equal [13,9,11,5,8,4,6]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe "Minimal Heap" do
|
|
22
|
+
|
|
23
|
+
before do
|
|
24
|
+
@min_heap = BinaryHeap.new(*@arr){|parent,child| parent < child}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should create heap from array." do
|
|
28
|
+
@min_heap.to_a.must_equal [4,5,6,8,11,9]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "#insert should insert new element to the heap maintaining heap relation." do
|
|
32
|
+
@min_heap.insert(3).to_a.must_equal [3,5,4,8,11,9,6]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'help'
|
|
2
|
+
|
|
3
|
+
describe BinarySearchTree do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
t = BinarySearchTree.new(7)
|
|
7
|
+
c1 = t.insert 5
|
|
8
|
+
c2 = t.insert 8
|
|
9
|
+
|
|
10
|
+
c3 = c1.insert 2
|
|
11
|
+
c1.insert 6
|
|
12
|
+
|
|
13
|
+
c3.insert 1
|
|
14
|
+
|
|
15
|
+
@bst = t
|
|
16
|
+
|
|
17
|
+
@bin_tree = BinaryTree.new
|
|
18
|
+
[2,5,8,9,11,12,14].each{|x| @bin_tree.insert(x)}
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should be valid Binary Search Tree." do
|
|
23
|
+
assert BinarySearchTree.valid?(@bst)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
it "not every Binary Tree is valid Binary Search Tree." do
|
|
28
|
+
refute BinarySearchTree.valid?(@bin_tree)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|