victory 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -0
  3. data/.rubocop.yml +11 -1
  4. data/README.md +4 -6
  5. data/Rakefile +11 -4
  6. data/USAGE.md +159 -0
  7. data/ext/algorithms/string/LICENSE.md +21 -0
  8. data/ext/algorithms/string/extconf.rb +4 -0
  9. data/ext/algorithms/string/string.c +68 -0
  10. data/ext/containers/bst/LICENSE.md +21 -0
  11. data/ext/containers/bst/bst.c +247 -0
  12. data/ext/containers/bst/extconf.rb +4 -0
  13. data/ext/containers/deque/LICENSE.md +21 -0
  14. data/ext/containers/deque/deque.c +247 -0
  15. data/ext/containers/deque/extconf.rb +4 -0
  16. data/ext/containers/rbtree_map/LICENSE.md +21 -0
  17. data/ext/containers/rbtree_map/extconf.rb +4 -0
  18. data/ext/containers/rbtree_map/rbtree.c +498 -0
  19. data/ext/containers/splaytree_map/LICENSE.md +21 -0
  20. data/ext/containers/splaytree_map/extconf.rb +4 -0
  21. data/ext/containers/splaytree_map/splaytree.c +419 -0
  22. data/ext/containers/xor_list/extconf.rb +4 -0
  23. data/ext/containers/xor_list/xor_list.c +122 -0
  24. data/lib/algorithms/search.rb +104 -0
  25. data/lib/algorithms/sort.rb +389 -0
  26. data/lib/algorithms/string.rb +29 -0
  27. data/lib/containers/deque.rb +193 -0
  28. data/lib/containers/heap.rb +524 -0
  29. data/lib/containers/kd_tree.rb +131 -0
  30. data/lib/containers/list.rb +81 -0
  31. data/lib/containers/prefix_tree.rb +61 -0
  32. data/lib/containers/priority_queue.rb +135 -0
  33. data/lib/containers/queue.rb +89 -0
  34. data/lib/containers/rb_tree_map.rb +420 -0
  35. data/lib/containers/splay_tree_map.rb +290 -0
  36. data/lib/containers/stack.rb +88 -0
  37. data/lib/containers/suffix_array.rb +92 -0
  38. data/lib/containers/trie.rb +204 -0
  39. data/lib/containers/tuple.rb +20 -0
  40. data/lib/victory/version.rb +1 -1
  41. data/lib/victory.rb +8 -1
  42. data/victory.gemspec +12 -3
  43. metadata +73 -12
  44. data/.idea/encodings.xml +0 -4
  45. data/.idea/misc.xml +0 -7
  46. data/.idea/modules.xml +0 -8
  47. data/.idea/victory.iml +0 -13
  48. data/.idea/workspace.xml +0 -233
  49. data/ext/victory/extconf.rb +0 -3
  50. data/ext/victory/victory.c +0 -9
  51. data/ext/victory/victory.h +0 -6
@@ -0,0 +1,389 @@
1
+ require 'containers/heap' # for heapsort
2
+
3
+ # rdoc
4
+ # This module implements sorting algorithms. Documentation is provided for each algorithm.
5
+ #
6
+ # MIT License
7
+ #
8
+ # Copyright (c) 2009 Kanwei Li
9
+ #
10
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ # of this software and associated documentation files (the "Software"), to deal
12
+ # in the Software without restriction, including without limitation the rights
13
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ # copies of the Software, and to permit persons to whom the Software is
15
+ # furnished to do so, subject to the following conditions:
16
+ #
17
+ # The above copyright notice and this permission notice shall be included in all
18
+ # copies or substantial portions of the Software.
19
+ #
20
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ # SOFTWARE.
27
+
28
+ module Algorithms::Sort
29
+ # Bubble sort: A very naive sort that keeps swapping elements until the container is sorted.
30
+ # Requirements: Needs to be able to compare elements with <=>, and the [] []= methods should
31
+ # be implemented for the container.
32
+ # Time Complexity: О(n^2)
33
+ # Space Complexity: О(n) total, O(1) auxiliary
34
+ # Stable: Yes
35
+ #
36
+ # Algorithms::Sort.bubble_sort [5, 4, 3, 1, 2] => [1, 2, 3, 4, 5]
37
+ def self.bubble_sort(container)
38
+ loop do
39
+ swapped = false
40
+ (container.size-1).times do |i|
41
+ if (container[i] <=> container[i+1]) == 1
42
+ container[i], container[i+1] = container[i+1], container[i] # Swap
43
+ swapped = true
44
+ end
45
+ end
46
+ break unless swapped
47
+ end
48
+ container
49
+ end
50
+
51
+ # Comb sort: A variation on bubble sort that dramatically improves performance.
52
+ # Source: http://yagni.com/combsort/
53
+ # Requirements: Needs to be able to compare elements with <=>, and the [] []= methods should
54
+ # be implemented for the container.
55
+ # Time Complexity: О(n^2)
56
+ # Space Complexity: О(n) total, O(1) auxiliary
57
+ # Stable: Yes
58
+ #
59
+ # Algorithms::Sort.comb_sort [5, 4, 3, 1, 2] => [1, 2, 3, 4, 5]
60
+ def self.comb_sort(container)
61
+ container
62
+ gap = container.size
63
+ loop do
64
+ gap = gap * 10/13
65
+ gap = 11 if gap == 9 || gap == 10
66
+ gap = 1 if gap < 1
67
+ swapped = false
68
+ (container.size - gap).times do |i|
69
+ if (container[i] <=> container[i + gap]) == 1
70
+ container[i], container[i+gap] = container[i+gap], container[i] # Swap
71
+ swapped = true
72
+ end
73
+ end
74
+ break if !swapped && gap == 1
75
+ end
76
+ container
77
+ end
78
+
79
+ # Selection sort: A naive sort that goes through the container and selects the smallest element,
80
+ # putting it at the beginning. Repeat until the end is reached.
81
+ # Requirements: Needs to be able to compare elements with <=>, and the [] []= methods should
82
+ # be implemented for the container.
83
+ # Time Complexity: О(n^2)
84
+ # Space Complexity: О(n) total, O(1) auxiliary
85
+ # Stable: Yes
86
+ #
87
+ # Algorithms::Sort.selection_sort [5, 4, 3, 1, 2] => [1, 2, 3, 4, 5]
88
+ def self.selection_sort(container)
89
+ 0.upto(container.size-1) do |i|
90
+ min = i
91
+ (i+1).upto(container.size-1) do |j|
92
+ min = j if (container[j] <=> container[min]) == -1
93
+ end
94
+ container[i], container[min] = container[min], container[i] # Swap
95
+ end
96
+ container
97
+ end
98
+
99
+ # Heap sort: Uses a heap (implemented by the Containers module) to sort the collection.
100
+ # Requirements: Needs to be able to compare elements with <=>
101
+ # Time Complexity: О(n^2)
102
+ # Space Complexity: О(n) total, O(1) auxiliary
103
+ # Stable: Yes
104
+ #
105
+ # Algorithms::Sort.heapsort [5, 4, 3, 1, 2] => [1, 2, 3, 4, 5]
106
+ def self.heapsort(container)
107
+ heap = Containers::Heap.new(container)
108
+ ary = []
109
+ ary << heap.pop until heap.empty?
110
+ ary
111
+ end
112
+
113
+ # Insertion sort: Elements are inserted sequentially into the right position.
114
+ # Requirements: Needs to be able to compare elements with <=>, and the [] []= methods should
115
+ # be implemented for the container.
116
+ # Time Complexity: О(n^2)
117
+ # Space Complexity: О(n) total, O(1) auxiliary
118
+ # Stable: Yes
119
+ #
120
+ # Algorithms::Sort.insertion_sort [5, 4, 3, 1, 2] => [1, 2, 3, 4, 5]
121
+ def self.insertion_sort(container)
122
+ return container if container.size < 2
123
+ (1..container.size-1).each do |i|
124
+ value = container[i]
125
+ j = i-1
126
+ while j >= 0 and container[j] > value do
127
+ container[j+1] = container[j]
128
+ j = j-1
129
+ end
130
+ container[j+1] = value
131
+ end
132
+ container
133
+ end
134
+
135
+ # Shell sort: Similar approach as insertion sort but slightly better.
136
+ # Requirements: Needs to be able to compare elements with <=>, and the [] []= methods should
137
+ # be implemented for the container.
138
+ # Time Complexity: О(n^2)
139
+ # Space Complexity: О(n) total, O(1) auxiliary
140
+ # Stable: Yes
141
+ #
142
+ # Algorithms::Sort.shell_sort [5, 4, 3, 1, 2] => [1, 2, 3, 4, 5]
143
+ def self.shell_sort(container)
144
+ increment = container.size/2
145
+ while increment > 0 do
146
+ (increment..container.size-1).each do |i|
147
+ temp = container[i]
148
+ j = i
149
+ while j >= increment && container[j - increment] > temp do
150
+ container[j] = container[j-increment]
151
+ j -= increment
152
+ end
153
+ container[j] = temp
154
+ end
155
+ increment = (increment == 2 ? 1 : (increment / 2.2).round)
156
+ end
157
+ container
158
+ end
159
+
160
+ # Quicksort: A divide-and-conquer sort that recursively partitions a container until it is sorted.
161
+ # Requirements: Container should implement #pop and include the Enumerable module.
162
+ # Time Complexity: О(n log n) average, O(n^2) worst-case
163
+ # Space Complexity: О(n) auxiliary
164
+ # Stable: No
165
+ #
166
+ # Algorithms::Sort.quicksort [5, 4, 3, 1, 2] => [1, 2, 3, 4, 5]
167
+ # def self.quicksort(container)
168
+ # return [] if container.empty?
169
+ #
170
+ # x, *xs = container
171
+ #
172
+ # quicksort(xs.select { |i| i < x }) + [x] + quicksort(xs.select { |i| i >= x })
173
+ # end
174
+
175
+ def self.partition(data, left, right)
176
+ pivot = data[front]
177
+ left += 1
178
+
179
+ while left <= right do
180
+ if data[frontUnknown] < pivot
181
+ back += 1
182
+ data[frontUnknown], data[back] = data[back], data[frontUnknown] # Swap
183
+ end
184
+
185
+ frontUnknown += 1
186
+ end
187
+
188
+ data[front], data[back] = data[back], data[front] # Swap
189
+ back
190
+ end
191
+
192
+
193
+ # def self.quicksort(container, left = 0, right = container.size - 1)
194
+ # if left < right
195
+ # middle = partition(container, left, right)
196
+ # quicksort(container, left, middle - 1)
197
+ # quicksort(container, middle + 1, right)
198
+ # end
199
+ # end
200
+
201
+ def self.quicksort(container)
202
+ bottom, top = [], []
203
+ top[0] = 0
204
+ bottom[0] = container.size
205
+ i = 0
206
+ while i >= 0 do
207
+ l = top[i]
208
+ r = bottom[i] - 1;
209
+ if l < r
210
+ pivot = container[l]
211
+ while l < r do
212
+ r -= 1 while (container[r] >= pivot && l < r)
213
+ if (l < r)
214
+ container[l] = container[r]
215
+ l += 1
216
+ end
217
+ l += 1 while (container[l] <= pivot && l < r)
218
+ if (l < r)
219
+ container[r] = container[l]
220
+ r -= 1
221
+ end
222
+ end
223
+ container[l] = pivot
224
+ top[i+1] = l + 1
225
+ bottom[i+1] = bottom[i]
226
+ bottom[i] = l
227
+ i += 1
228
+ else
229
+ i -= 1
230
+ end
231
+ end
232
+ container
233
+ end
234
+
235
+ # Mergesort: A stable divide-and-conquer sort that sorts small chunks of the container and then merges them together.
236
+ # Returns an array of the sorted elements.
237
+ # Requirements: Container should implement []
238
+ # Time Complexity: О(n log n) average and worst-case
239
+ # Space Complexity: О(n) auxiliary
240
+ # Stable: Yes
241
+ #
242
+ # Algorithms::Sort.mergesort [5, 4, 3, 1, 2] => [1, 2, 3, 4, 5]
243
+ def self.mergesort(container)
244
+ return container if container.size <= 1
245
+ mid = container.size / 2
246
+ left = container[0...mid]
247
+ right = container[mid...container.size]
248
+ merge(mergesort(left), mergesort(right))
249
+ end
250
+
251
+ def self.merge(left, right)
252
+ sorted = []
253
+ until left.empty? or right.empty?
254
+ left.first <= right.first ? sorted << left.shift : sorted << right.shift
255
+ end
256
+ sorted + left + right
257
+ end
258
+
259
+ # Dual-Pivot Quicksort is a variation of Quicksort by Vladimir Yaroslavskiy.
260
+ # This is an implementation of the algorithm as it was found in the original
261
+ # research paper:
262
+ #
263
+ # http://iaroslavski.narod.ru/quicksort/DualPivotQuicksort.pdf
264
+ #
265
+ # Mirror:
266
+ # http://codeblab.com/wp-content/uploads/2009/09/DualPivotQuicksort.pdf
267
+ #
268
+ # "This algorithm offers O(n log(n)) performance on many data sets that cause
269
+ # other quicksorts to degrade to quadratic performance, and is typically
270
+ # faster than traditional (one-pivot) Quicksort implementations."
271
+ # -- http://download.oracle.com/javase/7/docs/api/java/util/Arrays.html
272
+ #
273
+ # The algorithm was improved by Vladimir Yaroslavskiy, Jon Bentley, and
274
+ # Joshua Bloch, and was implemented as the default sort algorithm for
275
+ # primatives in Java 7.
276
+ #
277
+ # Implementation in the Java JDK as of November, 2011:
278
+ # http://www.docjar.com/html/api/java/util/DualPivotQuicksort.java.html
279
+ #
280
+ # It is proved that for the Dual-Pivot Quicksort the average number
281
+ # of comparisons is 2*n*ln(n), the average number of swaps is
282
+ # 0.8*n*ln(n), whereas classical Quicksort algorithm has 2*n*ln(n)
283
+ # and 1*n*ln(n) respectively. This has been fully examined mathematically
284
+ # and experimentally.
285
+ #
286
+ # Requirements: Container should implement #pop and include the Enumerable module.
287
+ # Time Complexity: О(n log n) average, О(n log n) worst-case
288
+ # Space Complexity: О(n) auxiliary
289
+ #
290
+ # Stable: No
291
+ #
292
+ # Algorithms::Sort.dualpivotquicksort [5, 4, 3, 1, 2] => [1, 2, 3, 4, 5]
293
+
294
+ def self.dualpivotquicksort(container)
295
+ return container if container.size <= 1
296
+ dualpivot(container, 0, container.size-1, 3)
297
+ end
298
+
299
+ def self.dualpivot(container, left=0, right=container.size-1, div=3)
300
+ length = right - left
301
+ if length < 27 # insertion sort for tiny array
302
+ container.each_with_index do |data,i|
303
+ j = i - 1
304
+ while j >= 0
305
+ break if container[j] <= data
306
+ container[j + 1] = container[j]
307
+ j = j - 1
308
+ end
309
+ container[j + 1] = data
310
+ end
311
+ else # full dual-pivot quicksort
312
+ third = length / div
313
+ # medians
314
+ m1 = left + third
315
+ m2 = right - third
316
+ if m1 <= left
317
+ m1 = left + 1
318
+ end
319
+ if m2 >= right
320
+ m2 = right - 1
321
+ end
322
+ if container[m1] < container[m2]
323
+ dualpivot_swap(container, m1, left)
324
+ dualpivot_swap(container, m2, right)
325
+ else
326
+ dualpivot_swap(container, m1, right)
327
+ dualpivot_swap(container, m2, left)
328
+ end
329
+ # pivots
330
+ pivot1 = container[left]
331
+ pivot2 = container[right]
332
+ # pointers
333
+ less = left + 1
334
+ great = right -1
335
+ # sorting
336
+ k = less
337
+ while k <= great
338
+ if container[k] < pivot1
339
+ dualpivot_swap(container, k, less += 1)
340
+ elsif container[k] > pivot2
341
+ while k < great && container[great] > pivot2
342
+ great -= 1
343
+ end
344
+ dualpivot_swap(container, k, great -= 1)
345
+ if container[k] < pivot1
346
+ dualpivot_swap(container, k, less += 1)
347
+ end
348
+ end
349
+ k += 1
350
+ end
351
+ # swaps
352
+ dist = great - less
353
+ if dist < 13
354
+ div += 1
355
+ end
356
+ dualpivot_swap(container, less-1, left)
357
+ dualpivot_swap(container, great+1, right)
358
+ # subarrays
359
+ dualpivot(container, left, less-2, div)
360
+ dualpivot(container, great+2, right, div)
361
+ # equal elements
362
+ if dist > length - 13 && pivot1 != pivot2
363
+ for k in less..great do
364
+ if container[k] == pivot1
365
+ dualpivot_swap(container, k, less)
366
+ less += 1
367
+ elsif container[k] == pivot2
368
+ dualpivot_swap(container, k, great)
369
+ great -= 1
370
+ if container[k] == pivot1
371
+ dualpivot_swap(container, k, less)
372
+ less += 1
373
+ end
374
+ end
375
+ end
376
+ end
377
+ # subarray
378
+ if pivot1 < pivot2
379
+ dualpivot(container, less, great, div)
380
+ end
381
+ container
382
+ end
383
+ end
384
+
385
+ def self.dualpivot_swap(container, i, j)
386
+ container[i], container[j] = container[j], container[i]
387
+ end
388
+ end
389
+
@@ -0,0 +1,29 @@
1
+ # rdoc
2
+ # This module implements string algorithms. Documentation is provided for each algorithm.
3
+ #
4
+ # MIT License
5
+ #
6
+ # Copyright (c) 2009 Kanwei Li
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files (the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be included in all
16
+ # copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ # SOFTWARE.
25
+
26
+ begin
27
+ require 'CString'
28
+ rescue LoadError
29
+ end
@@ -0,0 +1,193 @@
1
+ # rdoc
2
+ # A Deque is a container that allows items to be added and removed from both the front and back,
3
+ # acting as a combination of a Stack and Queue.
4
+ #
5
+ # This implementation uses a doubly-linked list, guaranteeing O(1) complexity for all operations.
6
+ #
7
+ #
8
+ # MIT License
9
+ #
10
+ # Copyright (c) 2009 Kanwei Li
11
+ #
12
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ # of this software and associated documentation files (the "Software"), to deal
14
+ # in the Software without restriction, including without limitation the rights
15
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ # copies of the Software, and to permit persons to whom the Software is
17
+ # furnished to do so, subject to the following conditions:
18
+ #
19
+ # The above copyright notice and this permission notice shall be included in all
20
+ # copies or substantial portions of the Software.
21
+ #
22
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ # SOFTWARE.
29
+ class Containers::RubyDeque
30
+ include Enumerable
31
+
32
+ Node = Struct.new(:left, :right, :obj)
33
+
34
+ # Create a new Deque. Takes an optional array argument to initialize the Deque.
35
+ #
36
+ # d = Containers::Deque.new([1, 2, 3])
37
+ # d.front #=> 1
38
+ # d.back #=> 3
39
+ def initialize(ary=[])
40
+ @front = nil
41
+ @back = nil
42
+ @size = 0
43
+ ary.to_a.each { |obj| push_back(obj) }
44
+ end
45
+
46
+ # Returns true if the Deque is empty, false otherwise.
47
+ def empty?
48
+ @size == 0
49
+ end
50
+
51
+ # Removes all the objects in the Deque.
52
+ def clear
53
+ @front = @back = nil
54
+ @size = 0
55
+ end
56
+
57
+ # Return the number of items in the Deque.
58
+ #
59
+ # d = Containers::Deque.new([1, 2, 3])
60
+ # d.size #=> 3
61
+ def size
62
+ @size
63
+ end
64
+ alias_method :length, :size
65
+
66
+ # Returns the object at the front of the Deque but does not remove it.
67
+ #
68
+ # d = Containers::Deque.new
69
+ # d.push_front(1)
70
+ # d.push_front(2)
71
+ # d.front #=> 2
72
+ def front
73
+ @front && @front.obj
74
+ end
75
+
76
+ # Returns the object at the back of the Deque but does not remove it.
77
+ #
78
+ # d = Containers::Deque.new
79
+ # d.push_front(1)
80
+ # d.push_front(2)
81
+ # d.back #=> 1
82
+ def back
83
+ @back && @back.obj
84
+ end
85
+
86
+ # Adds an object at the front of the Deque.
87
+ #
88
+ # d = Containers::Deque.new([1, 2, 3])
89
+ # d.push_front(0)
90
+ # d.pop_front #=> 0
91
+ def push_front(obj)
92
+ node = Node.new(nil, nil, obj)
93
+ if @front
94
+ node.right = @front
95
+ @front.left = node
96
+ @front = node
97
+ else
98
+ @front = @back = node
99
+ end
100
+ @size += 1
101
+ obj
102
+ end
103
+
104
+ # Adds an object at the back of the Deque.
105
+ #
106
+ # d = Containers::Deque.new([1, 2, 3])
107
+ # d.push_back(4)
108
+ # d.pop_back #=> 4
109
+ def push_back(obj)
110
+ node = Node.new(nil, nil, obj)
111
+ if @back
112
+ node.left = @back
113
+ @back.right = node
114
+ @back = node
115
+ else
116
+ @front = @back = node
117
+ end
118
+ @size += 1
119
+ obj
120
+ end
121
+
122
+ # Returns the object at the front of the Deque and removes it.
123
+ #
124
+ # d = Containers::Deque.new
125
+ # d.push_front(1)
126
+ # d.push_front(2)
127
+ # d.pop_front #=> 2
128
+ # d.size #=> 1
129
+ def pop_front
130
+ return nil unless @front
131
+ node = @front
132
+ if @size == 1
133
+ clear
134
+ return node.obj
135
+ else
136
+ @front.right.left = nil
137
+ @front = @front.right
138
+ end
139
+ @size -= 1
140
+ node.obj
141
+ end
142
+
143
+ # Returns the object at the back of the Deque and removes it.
144
+ #
145
+ # d = Containers::Deque.new
146
+ # d.push_front(1)
147
+ # d.push_front(2)
148
+ # d.pop_back #=> 1
149
+ # d.size #=> 1
150
+ def pop_back
151
+ return nil unless @back
152
+ node = @back
153
+ if @size == 1
154
+ clear
155
+ return node.obj
156
+ else
157
+ @back.left.right = nil
158
+ @back = @back.left
159
+ end
160
+ @size -= 1
161
+ node.obj
162
+ end
163
+
164
+ # Iterate over the Deque in FIFO order.
165
+ def each_forward
166
+ return unless @front
167
+ node = @front
168
+ while node
169
+ yield node.obj
170
+ node = node.right
171
+ end
172
+ end
173
+ alias_method :each, :each_forward
174
+
175
+ # Iterate over the Deque in LIFO order.
176
+ def each_backward
177
+ return unless @back
178
+ node = @back
179
+ while node
180
+ yield node.obj
181
+ node = node.left
182
+ end
183
+ end
184
+ alias_method :reverse_each, :each_backward
185
+
186
+ end
187
+
188
+ begin
189
+ require 'CDeque'
190
+ Containers::Deque = Containers::CDeque
191
+ rescue LoadError # C Version could not be found, try ruby version
192
+ Containers::Deque = Containers::RubyDeque
193
+ end