algorithm_selector 0.1.0
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.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.gitignore +1 -0
- data/.yardoc/checksums +2 -0
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/.yardoc/proxy_types +0 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +45 -0
- data/Rakefile +6 -0
- data/algorithm_selector.gemspec +35 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/doc/AlgorithmSelector.html +505 -0
- data/doc/BSTNode.html +440 -0
- data/doc/BinaryTree.html +572 -0
- data/doc/LinkNode.html +440 -0
- data/doc/LinkedList.html +879 -0
- data/doc/Queue.html +569 -0
- data/doc/Searches.html +442 -0
- data/doc/Sorts.html +916 -0
- data/doc/Stack.html +723 -0
- data/doc/_index.html +183 -0
- data/doc/class_list.html +51 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +58 -0
- data/doc/css/style.css +481 -0
- data/doc/file.README.html +129 -0
- data/doc/file_list.html +56 -0
- data/doc/frames.html +17 -0
- data/doc/index.html +129 -0
- data/doc/js/app.js +243 -0
- data/doc/js/full_list.js +216 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +507 -0
- data/doc/top-level-namespace.html +114 -0
- data/lib/.DS_Store +0 -0
- data/lib/algorithm_selector.rb +562 -0
- data/lib/algorithm_selector/version.rb +3 -0
- metadata +129 -0
@@ -0,0 +1,114 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
+
<title>
|
7
|
+
Top Level Namespace
|
8
|
+
|
9
|
+
— Documentation by YARD 0.9.4
|
10
|
+
|
11
|
+
</title>
|
12
|
+
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
|
14
|
+
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
|
16
|
+
|
17
|
+
<script type="text/javascript" charset="utf-8">
|
18
|
+
pathId = "";
|
19
|
+
relpath = '';
|
20
|
+
</script>
|
21
|
+
|
22
|
+
|
23
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
24
|
+
|
25
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
26
|
+
|
27
|
+
|
28
|
+
</head>
|
29
|
+
<body>
|
30
|
+
<div class="nav_wrap">
|
31
|
+
<iframe id="nav" src="class_list.html"></iframe>
|
32
|
+
<div id="resizer"></div>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div id="main" tabindex="-1">
|
36
|
+
<div id="header">
|
37
|
+
<div id="menu">
|
38
|
+
|
39
|
+
<a href="_index.html">Index</a> »
|
40
|
+
|
41
|
+
|
42
|
+
<span class="title">Top Level Namespace</span>
|
43
|
+
|
44
|
+
</div>
|
45
|
+
|
46
|
+
<div id="search">
|
47
|
+
|
48
|
+
<a class="full_list_link" id="class_list_link"
|
49
|
+
href="class_list.html">
|
50
|
+
|
51
|
+
<svg width="24" height="24">
|
52
|
+
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
53
|
+
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
54
|
+
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
55
|
+
</svg>
|
56
|
+
</a>
|
57
|
+
|
58
|
+
</div>
|
59
|
+
<div class="clear"></div>
|
60
|
+
</div>
|
61
|
+
|
62
|
+
<iframe id="search_frame" src="class_list.html"></iframe>
|
63
|
+
|
64
|
+
<div id="content"><h1>Top Level Namespace
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
</h1>
|
69
|
+
<div class="box_info">
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
</div>
|
82
|
+
|
83
|
+
<h2>Defined Under Namespace</h2>
|
84
|
+
<p class="children">
|
85
|
+
|
86
|
+
|
87
|
+
<strong class="modules">Modules:</strong> <span class='object_link'><a href="AlgorithmSelector.html" title="AlgorithmSelector (module)">AlgorithmSelector</a></span>
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
<strong class="classes">Classes:</strong> <span class='object_link'><a href="BSTNode.html" title="BSTNode (class)">BSTNode</a></span>, <span class='object_link'><a href="BinaryTree.html" title="BinaryTree (class)">BinaryTree</a></span>, <span class='object_link'><a href="LinkNode.html" title="LinkNode (class)">LinkNode</a></span>, <span class='object_link'><a href="LinkedList.html" title="LinkedList (class)">LinkedList</a></span>, <span class='object_link'><a href="Queue.html" title="Queue (class)">Queue</a></span>, <span class='object_link'><a href="Searches.html" title="Searches (class)">Searches</a></span>, <span class='object_link'><a href="Sorts.html" title="Sorts (class)">Sorts</a></span>, <span class='object_link'><a href="Stack.html" title="Stack (class)">Stack</a></span>
|
92
|
+
|
93
|
+
|
94
|
+
</p>
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
|
104
|
+
</div>
|
105
|
+
|
106
|
+
<div id="footer">
|
107
|
+
Generated on Fri Jul 22 11:22:30 2016 by
|
108
|
+
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
109
|
+
0.9.4 (ruby-2.1.2).
|
110
|
+
</div>
|
111
|
+
|
112
|
+
</div>
|
113
|
+
</body>
|
114
|
+
</html>
|
data/lib/.DS_Store
ADDED
Binary file
|
@@ -0,0 +1,562 @@
|
|
1
|
+
require "algorithm_selector/version"
|
2
|
+
|
3
|
+
module AlgorithmSelector
|
4
|
+
extend self
|
5
|
+
|
6
|
+
# get all algorithms
|
7
|
+
def all(type, array, num_tests=1, target=nil)
|
8
|
+
if type == "sort"
|
9
|
+
Sorts.new.all(array, num_tests)
|
10
|
+
elsif type == "search"
|
11
|
+
Searches.new.all(array, num_tests, target)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# get best algorithm
|
16
|
+
def best(type, array, num_tests=1, target=nil)
|
17
|
+
if type == "sort"
|
18
|
+
Sorts.new.best(array, num_tests)
|
19
|
+
elsif type == "search"
|
20
|
+
Searches.new.best(array, num_tests, target)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# get one algorithm by name
|
25
|
+
def analyze(type, array, algorithm_name, num_tests=1, target=nil)
|
26
|
+
if type == "sort"
|
27
|
+
Sorts.new.analyze(array, algorithm_name, num_tests)
|
28
|
+
elsif type == "search"
|
29
|
+
Searches.new.analyze(array, algorithm_name, num_tests, target)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# compare two algorithms
|
34
|
+
def compare(type, array, first_algorithm_name, second_algorithm_name, num_tests=1, target=nil)
|
35
|
+
if type == "sort"
|
36
|
+
Sorts.new.compare(array, first_algorithm_name, second_algorithm_name, num_tests)
|
37
|
+
elsif type == "search"
|
38
|
+
Searches.new.compare(array, first_algorithm_name, second_algorithm_name, num_tests, target)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# call sort algorithm method
|
43
|
+
def sort(array, algorithm_name)
|
44
|
+
method = Sorts.new.method(algorithm_name)
|
45
|
+
method.call(array)
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
# Sorts class
|
51
|
+
class Sorts
|
52
|
+
# Show all results from sorting algorithms
|
53
|
+
def all(array, num_tests)
|
54
|
+
{
|
55
|
+
sorted: merge_sort(array),
|
56
|
+
results: {
|
57
|
+
bubble_sort: display_time(Proc.new {bubble_sort(array)}, num_tests),
|
58
|
+
insertion_sort: display_time(Proc.new {insertion_sort(array)}, num_tests),
|
59
|
+
selection_sort: display_time(Proc.new {selection_sort(array)}, num_tests),
|
60
|
+
merge_sort: display_time(Proc.new {merge_sort(array)}, num_tests),
|
61
|
+
quick_sort: display_time(Proc.new {quick_sort(array)}, num_tests)
|
62
|
+
}
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
# Show the best sorting algorithm
|
67
|
+
def best(array, num_tests)
|
68
|
+
hash = all(array, num_tests)
|
69
|
+
best_time = 0
|
70
|
+
best_algorithm = {}
|
71
|
+
hash[:results].each do |key, val|
|
72
|
+
if val < best_time || best_time == 0
|
73
|
+
best_time = val
|
74
|
+
best_algorithm = Hash[key, val]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
{
|
78
|
+
best_algorithm.keys[0] => best_algorithm[best_algorithm.keys[0]]
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
# Analyze specific sorting algorithm by name
|
83
|
+
def analyze(array, algorithm, num_tests)
|
84
|
+
hash = all(array, num_tests)
|
85
|
+
alg = {}
|
86
|
+
hash[:results].each do |key, val|
|
87
|
+
if algorithm.to_sym == key
|
88
|
+
alg = Hash[key, val]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
{
|
92
|
+
sorted: hash[:sorted],
|
93
|
+
alg.keys[0] => alg[alg.keys[0]]
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
# Compare two algorithms for data set
|
98
|
+
def compare(array, first_algorithm, second_algorithm, num_tests)
|
99
|
+
hash = all(array, num_tests)
|
100
|
+
first = {}
|
101
|
+
second = {}
|
102
|
+
hash[:results].each do |key, val|
|
103
|
+
if first_algorithm.to_sym == key
|
104
|
+
first = Hash[key, val]
|
105
|
+
elsif second_algorithm.to_sym == key
|
106
|
+
second = Hash[key, val]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
{
|
110
|
+
first.keys[0] => first[first.keys[0]],
|
111
|
+
second.keys[0] => second[second.keys[0]]
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
# Bubble sort
|
116
|
+
# Worst-Case Space Complexity: O(1)
|
117
|
+
# Averge-Case Time Complexity: O(n^2)
|
118
|
+
# Worst-Case Time Complexity: O(n^2)
|
119
|
+
def bubble_sort(array)
|
120
|
+
return array if array.length < 2
|
121
|
+
switched = true
|
122
|
+
until switched == false
|
123
|
+
switched = false
|
124
|
+
(1...array.length).each do |i|
|
125
|
+
if array[i-1] > array[i]
|
126
|
+
temp = array[i]
|
127
|
+
array[i] = array[i-1]
|
128
|
+
array[i-1] = temp
|
129
|
+
switched = true
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
return array
|
134
|
+
end
|
135
|
+
|
136
|
+
# Insertion sort
|
137
|
+
# Worst-Case Space Complexity: O(1)
|
138
|
+
# Averge-Case Time Complexity: O(n^2)
|
139
|
+
# Worst-Case Time Complexity: O(n^2)
|
140
|
+
def insertion_sort(array)
|
141
|
+
return array if array.length < 2
|
142
|
+
(1...array.length).to_a do |i|
|
143
|
+
value = array[i]
|
144
|
+
j = i - 1
|
145
|
+
while (j >= 0 && array[j] > value) do
|
146
|
+
array[j+1] = array[j]
|
147
|
+
j = j - 1
|
148
|
+
end
|
149
|
+
array[j+1] = value
|
150
|
+
end
|
151
|
+
array
|
152
|
+
end
|
153
|
+
|
154
|
+
# Selection sort
|
155
|
+
# Worst-Case Space Complexity: O(1)
|
156
|
+
# Averge-Case Time Complexity: O(n^2)
|
157
|
+
# Worst-Case Time Complexity: O(n^2)
|
158
|
+
def selection_sort(array)
|
159
|
+
(0...array.length-1).to_a.each do |i|
|
160
|
+
min = i
|
161
|
+
(i+1...array.length).to_a.each do |j|
|
162
|
+
if (array[j] < array[min])
|
163
|
+
min = j
|
164
|
+
end
|
165
|
+
end
|
166
|
+
if min != i
|
167
|
+
array[min], array[i] = array[i], array[min]
|
168
|
+
end
|
169
|
+
end
|
170
|
+
return array
|
171
|
+
end
|
172
|
+
|
173
|
+
# Merge sort
|
174
|
+
# Worst-Case Space Complexity: O(n)
|
175
|
+
# Averge-Case Time Complexity: O(n log(n))
|
176
|
+
# Worst-Case Time Complexity: O(n log(n))
|
177
|
+
def merge_sort(array)
|
178
|
+
return array if array.length < 2
|
179
|
+
middle = array.length/2
|
180
|
+
left = array[0...middle]
|
181
|
+
right = array[middle...array.length]
|
182
|
+
merge(merge_sort(left), merge_sort(right))
|
183
|
+
end
|
184
|
+
|
185
|
+
# Quick sort
|
186
|
+
# Worst-Case Space Complexity: O(log(n))
|
187
|
+
# Averge-Case Time Complexity: O(n log(n))
|
188
|
+
# Worst-Case Time Complexity: O(n^2)
|
189
|
+
def quick_sort(array)
|
190
|
+
return array if array.count < 2
|
191
|
+
pivot = array[0]
|
192
|
+
left = array.select {|el| el < pivot}
|
193
|
+
right = array.select {|el| el > pivot}
|
194
|
+
quick_sort(left) + [pivot] + quick_sort(right)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
class Searches
|
199
|
+
def all(array, num_tests, target)
|
200
|
+
stack = Stack.new(array.length, array)
|
201
|
+
queue = Queue.new(array.length, array)
|
202
|
+
linked_list = LinkedList.new(array)
|
203
|
+
binary_tree = BinaryTree.new(array)
|
204
|
+
{
|
205
|
+
found: stack.search(target),
|
206
|
+
results:
|
207
|
+
{
|
208
|
+
stack: display_time(Proc.new {stack.search(target)}, num_tests),
|
209
|
+
queue: display_time(Proc.new {queue.search(target)}, num_tests),
|
210
|
+
linked_list: display_time(Proc.new {linked_list.search(target)}, num_tests),
|
211
|
+
binary_tree: display_time(Proc.new {binary_tree.search(target)}, num_tests)
|
212
|
+
}
|
213
|
+
}
|
214
|
+
end
|
215
|
+
|
216
|
+
def best(array, num_tests, target)
|
217
|
+
hash = all(array, num_tests, target)
|
218
|
+
best_time = 0
|
219
|
+
best_algorithm = {}
|
220
|
+
hash[:results].each do |key, val|
|
221
|
+
if val < best_time || best_time == 0
|
222
|
+
best_time = val
|
223
|
+
best_algorithm = Hash[key, val]
|
224
|
+
end
|
225
|
+
end
|
226
|
+
{
|
227
|
+
best_algorithm.keys[0] => best_algorithm[best_algorithm.keys[0]]
|
228
|
+
}
|
229
|
+
end
|
230
|
+
|
231
|
+
def analyze(array, algorithm, num_tests, target)
|
232
|
+
hash = all(array, num_tests, target)
|
233
|
+
alg = {}
|
234
|
+
hash[:results].each do |key, val|
|
235
|
+
if algorithm.to_sym == key
|
236
|
+
alg = Hash[key, val]
|
237
|
+
end
|
238
|
+
end
|
239
|
+
{
|
240
|
+
found: hash[:found],
|
241
|
+
alg.keys[0] => alg[alg.keys[0]]
|
242
|
+
}
|
243
|
+
end
|
244
|
+
|
245
|
+
def compare(array, first_algorithm, second_algorithm, num_tests, target)
|
246
|
+
hash = all(array, num_tests, target)
|
247
|
+
first = {}
|
248
|
+
second = {}
|
249
|
+
hash[:results].each do |key, val|
|
250
|
+
if first_algorithm.to_sym == key
|
251
|
+
first = Hash[key, val]
|
252
|
+
elsif second_algorithm.to_sym == key
|
253
|
+
second = Hash[key, val]
|
254
|
+
end
|
255
|
+
end
|
256
|
+
{
|
257
|
+
first.keys[0] => first[first.keys[0]],
|
258
|
+
second.keys[0] => second[second.keys[0]]
|
259
|
+
}
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
# Stack data structure
|
264
|
+
# Worst-Case Space Complexity: O(n)
|
265
|
+
class Stack
|
266
|
+
def initialize(size, array=[])
|
267
|
+
@size = size
|
268
|
+
@store = Array.new(@size)
|
269
|
+
@top = -1
|
270
|
+
array.each { |el| push(el) }
|
271
|
+
end
|
272
|
+
|
273
|
+
# Search, Average-Case Time Complexity: O(n)
|
274
|
+
# Search, Worst-Case Time Complexity: O(n)
|
275
|
+
def search(target)
|
276
|
+
found = false
|
277
|
+
new_stack = Stack.new(@size)
|
278
|
+
until empty? do
|
279
|
+
new_stack.push(pop)
|
280
|
+
if new_stack.look == target
|
281
|
+
found = true
|
282
|
+
break
|
283
|
+
end
|
284
|
+
end
|
285
|
+
push(new_stack.pop) until new_stack.empty?
|
286
|
+
found
|
287
|
+
end
|
288
|
+
|
289
|
+
# Deletion, Worst-Case Time Complexity: O(1)
|
290
|
+
def pop
|
291
|
+
if empty?
|
292
|
+
nil
|
293
|
+
else
|
294
|
+
popped = @store[@top]
|
295
|
+
@store[@top] = nil
|
296
|
+
@top = @top.pred
|
297
|
+
popped
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
# Insertion, Worst-Case Time Complexity: O(1)
|
302
|
+
def push(el)
|
303
|
+
if full? or el.nil?
|
304
|
+
nil
|
305
|
+
else
|
306
|
+
@top = @top.succ
|
307
|
+
@store[@top] = el
|
308
|
+
self
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
def size
|
313
|
+
@size
|
314
|
+
end
|
315
|
+
|
316
|
+
def look
|
317
|
+
@store[@top]
|
318
|
+
end
|
319
|
+
|
320
|
+
def full?
|
321
|
+
@top == (@size - 1)
|
322
|
+
end
|
323
|
+
|
324
|
+
def empty?
|
325
|
+
@top == -1
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
# Queue data structure
|
330
|
+
# Worst-Case Space Complexity: O(n)
|
331
|
+
class Queue
|
332
|
+
def initialize(size, array=[])
|
333
|
+
@size = size
|
334
|
+
@store = Array.new(@size)
|
335
|
+
@head, @tail = -1, 0
|
336
|
+
|
337
|
+
# initialize Queue with array if given
|
338
|
+
array.each { |el| enqueue(el) }
|
339
|
+
end
|
340
|
+
|
341
|
+
# Search, Worst-Case Time Complexity: O(n)
|
342
|
+
def search(target)
|
343
|
+
found = false
|
344
|
+
@size.times do
|
345
|
+
found = true if look == target
|
346
|
+
enqueue(dequeue)
|
347
|
+
end
|
348
|
+
found
|
349
|
+
end
|
350
|
+
|
351
|
+
# Deletion, Worst-Case Time Complexity: O(1)
|
352
|
+
def dequeue
|
353
|
+
if empty?
|
354
|
+
nil
|
355
|
+
else
|
356
|
+
@tail = @tail.succ
|
357
|
+
dequeued = @store[@head]
|
358
|
+
@store.unshift(nil)
|
359
|
+
@store.pop
|
360
|
+
dequeued
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
# Insertion, Worst-Case Time Complexity: O(1)
|
365
|
+
def enqueue(el)
|
366
|
+
if full? or el.nil?
|
367
|
+
nil
|
368
|
+
else
|
369
|
+
@tail = @tail.pred
|
370
|
+
@store[@tail] = el
|
371
|
+
self
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
def size
|
376
|
+
@size
|
377
|
+
end
|
378
|
+
|
379
|
+
def look
|
380
|
+
@store[@head]
|
381
|
+
end
|
382
|
+
|
383
|
+
private
|
384
|
+
|
385
|
+
def empty?
|
386
|
+
@head == -1 and @tail == 0
|
387
|
+
end
|
388
|
+
|
389
|
+
def full?
|
390
|
+
@tail.abs == (@size)
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
# Singly-Linked List data structure
|
395
|
+
# Worst-Case Space Complexity: O(n)
|
396
|
+
class LinkedList
|
397
|
+
include Enumerable
|
398
|
+
|
399
|
+
def initialize(array=[])
|
400
|
+
@head = LinkNode.new
|
401
|
+
@tail = LinkNode.new
|
402
|
+
@head.next = @tail
|
403
|
+
@tail.prev = @head
|
404
|
+
array.each { |i| insert(i) }
|
405
|
+
end
|
406
|
+
|
407
|
+
# Search, Worst-Case Time Complexity: O(n)
|
408
|
+
def search(target)
|
409
|
+
each { |current_link| return current_link.val if current_link.val == target }
|
410
|
+
end
|
411
|
+
|
412
|
+
def [](i)
|
413
|
+
each_with_index { |link, j| return link if i == j }
|
414
|
+
nil
|
415
|
+
end
|
416
|
+
|
417
|
+
def first
|
418
|
+
empty? ? nil : @head.next
|
419
|
+
end
|
420
|
+
|
421
|
+
def last
|
422
|
+
empty? ? nil : @tail.prev
|
423
|
+
end
|
424
|
+
|
425
|
+
def empty?
|
426
|
+
@head.next == @tail
|
427
|
+
end
|
428
|
+
|
429
|
+
def get(val)
|
430
|
+
each { |link| return link.val if link.val == val }
|
431
|
+
nil
|
432
|
+
end
|
433
|
+
|
434
|
+
def include?(val)
|
435
|
+
any? { |link| link.val == val }
|
436
|
+
end
|
437
|
+
|
438
|
+
# Insertion, Worst-Case Time Complexity: O(1)
|
439
|
+
def insert(val)
|
440
|
+
each { |link| return link.val = val if link.val == val }
|
441
|
+
new_link = LinkNode.new(val)
|
442
|
+
@tail.prev.next = new_link
|
443
|
+
new_link.prev = @tail.prev
|
444
|
+
new_link.next = @tail
|
445
|
+
@tail.prev = new_link
|
446
|
+
new_link
|
447
|
+
end
|
448
|
+
|
449
|
+
# Deletion, Worst-Case Time Complexity: O(1)
|
450
|
+
def remove(val)
|
451
|
+
each do |link|
|
452
|
+
if link.val == val
|
453
|
+
link.prev.next = link.next
|
454
|
+
link.next.prev = link.prev
|
455
|
+
link.next, link.prev = nil, nil
|
456
|
+
return link.val
|
457
|
+
end
|
458
|
+
end
|
459
|
+
nil
|
460
|
+
end
|
461
|
+
|
462
|
+
def each
|
463
|
+
current_link = @head.next
|
464
|
+
until current_link == @tail
|
465
|
+
yield current_link
|
466
|
+
current_link = current_link.next
|
467
|
+
end
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
# Binary Search Tree data structure
|
472
|
+
# Worst-Case Space Complexity: O(n)
|
473
|
+
class BinaryTree
|
474
|
+
attr_accessor :root
|
475
|
+
|
476
|
+
def initialize(array=[], root_val=nil)
|
477
|
+
@root = BSTNode.new(root_val)
|
478
|
+
array.each { |i| insert(i) }
|
479
|
+
end
|
480
|
+
|
481
|
+
# Search, Worst-Case Time Complexity: O(n)
|
482
|
+
def search(target)
|
483
|
+
return nil if @root.nil?
|
484
|
+
return search_in_tree(@root, target)
|
485
|
+
end
|
486
|
+
|
487
|
+
def search_in_tree(tree_node, target)
|
488
|
+
return nil if tree_node.nil?
|
489
|
+
return tree_node.val if target == tree_node.val
|
490
|
+
if target < tree_node.val
|
491
|
+
search_in_tree(tree_node.left, target)
|
492
|
+
else
|
493
|
+
search_in_tree(tree_node.right, target)
|
494
|
+
end
|
495
|
+
end
|
496
|
+
|
497
|
+
# Insertion, Worst-Case Time Complexity: O(n)
|
498
|
+
def insert(val)
|
499
|
+
new_node = BSTNode.new(val)
|
500
|
+
@root = new_node and return unless @root.val
|
501
|
+
insert_to_tree(@root, new_node)
|
502
|
+
end
|
503
|
+
|
504
|
+
def insert_to_tree(tree_node, new_node)
|
505
|
+
tree_node = new_node and return if tree_node.nil?
|
506
|
+
return tree_node if tree_node.val == new_node.val
|
507
|
+
if new_node.val > tree_node.val
|
508
|
+
insert_to_tree(tree_node.right, new_node) unless tree_node.right.nil?
|
509
|
+
tree_node.right = new_node
|
510
|
+
else
|
511
|
+
insert_to_tree(tree_node.left, new_node) unless tree_node.left.nil?
|
512
|
+
tree_node.left = new_node
|
513
|
+
end
|
514
|
+
end
|
515
|
+
end
|
516
|
+
|
517
|
+
private
|
518
|
+
|
519
|
+
# Helper method to get time required for method to run
|
520
|
+
def display_time(prc, num_tests)
|
521
|
+
total = 0
|
522
|
+
num_tests.times do
|
523
|
+
start = Time.now
|
524
|
+
prc.call
|
525
|
+
finish = Time.now
|
526
|
+
total = total + (finish - start)
|
527
|
+
end
|
528
|
+
total/num_tests
|
529
|
+
end
|
530
|
+
|
531
|
+
# Helper method for merge_sort
|
532
|
+
def merge(left, right)
|
533
|
+
array = []
|
534
|
+
until left.length == 0 || right.length == 0
|
535
|
+
if left.first > right.first
|
536
|
+
array << right.shift
|
537
|
+
else
|
538
|
+
array << left.shift
|
539
|
+
end
|
540
|
+
end
|
541
|
+
array.concat(left).concat(right)
|
542
|
+
end
|
543
|
+
|
544
|
+
# Node helper class for Linked List
|
545
|
+
class LinkNode
|
546
|
+
attr_accessor :val, :next, :prev
|
547
|
+
def initialize(val=nil)
|
548
|
+
@val = val
|
549
|
+
@next = nil
|
550
|
+
@prev = nil
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
# Node helper class for Binary Search Tree
|
555
|
+
class BSTNode
|
556
|
+
attr_accessor :val, :left, :right
|
557
|
+
def initialize(val=nil, left=nil, right=nil)
|
558
|
+
@val = val
|
559
|
+
@left = left
|
560
|
+
@right = right
|
561
|
+
end
|
562
|
+
end
|