dsa-ruby 1.0.0 → 1.0.2
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 +4 -4
- data/README.md +9 -3
- data/lib/dsa-ruby/binary_search_tree.rb +258 -123
- data/lib/dsa-ruby/deque.rb +136 -55
- data/lib/dsa-ruby/heap.rb +235 -107
- data/lib/dsa-ruby/linked_list.rb +218 -0
- data/lib/dsa-ruby/priority_queue.rb +107 -41
- data/lib/dsa-ruby/queue.rb +72 -26
- data/lib/dsa-ruby/stack.rb +72 -26
- data/lib/dsa-ruby/trie.rb +109 -51
- data/lib/dsa-ruby/union_find.rb +93 -38
- data/lib/dsa-ruby/version.rb +8 -1
- metadata +15 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 263fc0d28c00fb0c51f2728871cc4f13e5f8d5d8c2011cd42523d440003bcd3e
|
|
4
|
+
data.tar.gz: 72d323d5c5b3527ee5ad9c4ec85b2949ff1ec90a6258928e83ced26358bc7466
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8d0dced01fb73b0a2e76d32795bbf57ffb84ffeaee0d790089d63e5e33365a7113247ede84e080b6e4fdcf4b30ad0459e42f81ed42bc6c18e7d49b29ad3cbcb6
|
|
7
|
+
data.tar.gz: 6855c1c3e893b55ae698e966094117d5f3105f39c4724bcd09fb478570ebd4ade85d6817f24b19172cd3a3787b0b625360ef49cdb1a5b100cc263a1cdd067d8c
|
data/README.md
CHANGED
|
@@ -24,8 +24,7 @@ require "dsa-ruby"
|
|
|
24
24
|
### MinHeap / MaxHeap
|
|
25
25
|
|
|
26
26
|
```ruby
|
|
27
|
-
heap = DSA::MinHeap.new
|
|
28
|
-
heap.push(5, 3, 7, 1)
|
|
27
|
+
heap = DSA::MinHeap.new([5, 3, 7, 1])
|
|
29
28
|
heap.pop # => 1
|
|
30
29
|
heap.peek # => 3
|
|
31
30
|
|
|
@@ -33,6 +32,13 @@ max_heap = DSA::MaxHeap.new([5, 3, 7, 1])
|
|
|
33
32
|
max_heap.pop # => 7
|
|
34
33
|
```
|
|
35
34
|
|
|
35
|
+
Or build incrementally with chained pushes:
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
heap = DSA::MinHeap.new
|
|
39
|
+
heap.push(5).push(3).push(7).push(1)
|
|
40
|
+
```
|
|
41
|
+
|
|
36
42
|
### PriorityQueue
|
|
37
43
|
|
|
38
44
|
```ruby
|
|
@@ -58,7 +64,7 @@ dq.pop_front # => 1
|
|
|
58
64
|
dq.pop_back # => 2
|
|
59
65
|
|
|
60
66
|
# Enumerable support
|
|
61
|
-
dq.push_back(1
|
|
67
|
+
dq.push_back(1).push_back(2).push_back(3)
|
|
62
68
|
dq.map { |x| x * 2 } # => [2, 4, 6]
|
|
63
69
|
```
|
|
64
70
|
|
|
@@ -1,154 +1,289 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# DSA::BinarySearchTree - A binary search tree data structure.
|
|
2
|
+
#
|
|
3
|
+
# Supports insertion, deletion, search, and tree traversals.
|
|
4
|
+
# Duplicate values are not inserted.
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# bst = DSA::BinarySearchTree.new
|
|
8
|
+
# bst.insert(5).insert(3).insert(7).insert(1).insert(4)
|
|
9
|
+
# bst.search(3) # => true
|
|
10
|
+
# bst.min # => 1
|
|
11
|
+
# bst.max # => 7
|
|
12
|
+
# bst.inorder # => [1, 3, 4, 5, 7]
|
|
13
|
+
# bst.preorder # => [5, 3, 1, 4, 7]
|
|
14
|
+
# bst.postorder # => [1, 4, 3, 7, 5]
|
|
15
|
+
# bst.delete(3)
|
|
16
|
+
class DSA::BinarySearchTree
|
|
17
|
+
# Internal node structure for the binary search tree.
|
|
18
|
+
#
|
|
19
|
+
# @!attribute [rw] val
|
|
20
|
+
# @return [Comparable] the value stored in the node
|
|
21
|
+
# @!attribute [rw] left
|
|
22
|
+
# @return [Node, nil] the left child node
|
|
23
|
+
# @!attribute [rw] right
|
|
24
|
+
# @return [Node, nil] the right child node
|
|
25
|
+
Node = Struct.new(:val, :left, :right, keyword_init: true)
|
|
4
26
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@size += 1 if added
|
|
13
|
-
self
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def search(val)
|
|
17
|
-
!!find_node(@root, val)
|
|
18
|
-
end
|
|
27
|
+
# Initialize a new empty binary search tree.
|
|
28
|
+
#
|
|
29
|
+
# @return [DSA::BinarySearchTree] a new empty tree
|
|
30
|
+
def initialize
|
|
31
|
+
@root = nil
|
|
32
|
+
@size = 0
|
|
33
|
+
end
|
|
19
34
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
35
|
+
# Inserts a value into the tree. Duplicates are ignored.
|
|
36
|
+
#
|
|
37
|
+
# @param val [Comparable] the value to insert
|
|
38
|
+
# @return [DSA::BinarySearchTree] self for method chaining
|
|
39
|
+
# @example
|
|
40
|
+
# bst.insert(5).insert(3).insert(7)
|
|
41
|
+
def insert(val)
|
|
42
|
+
@root, added = insert_recursive(@root, val)
|
|
43
|
+
@size += 1 if added
|
|
44
|
+
self
|
|
45
|
+
end
|
|
25
46
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
47
|
+
# Searches for a value in the tree.
|
|
48
|
+
#
|
|
49
|
+
# @param val [Comparable] the value to search for
|
|
50
|
+
# @return [Boolean] true if the value exists in the tree
|
|
51
|
+
# @example
|
|
52
|
+
# bst.insert(5)
|
|
53
|
+
# bst.search(5) # => true
|
|
54
|
+
# bst.search(3) # => false
|
|
55
|
+
def search(val)
|
|
56
|
+
!!find_node(@root, val)
|
|
57
|
+
end
|
|
30
58
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
59
|
+
# Deletes a value from the tree if it exists.
|
|
60
|
+
#
|
|
61
|
+
# @param val [Comparable] the value to delete
|
|
62
|
+
# @return [Boolean] true if the value was deleted, false if not found
|
|
63
|
+
# @example
|
|
64
|
+
# bst.insert(5).insert(3)
|
|
65
|
+
# bst.delete(3) # => true
|
|
66
|
+
# bst.delete(8) # => false
|
|
67
|
+
def delete(val)
|
|
68
|
+
@root, deleted = delete_recursive(@root, val)
|
|
69
|
+
@size -= 1 if deleted
|
|
70
|
+
deleted
|
|
71
|
+
end
|
|
35
72
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
73
|
+
# Returns the minimum value in the tree.
|
|
74
|
+
#
|
|
75
|
+
# @return [Comparable] the minimum value
|
|
76
|
+
# @raise [IndexError] if the tree is empty
|
|
77
|
+
# @example
|
|
78
|
+
# bst.insert(5).insert(3).insert(1)
|
|
79
|
+
# bst.min # => 1
|
|
80
|
+
def min
|
|
81
|
+
raise IndexError, "tree is empty" if empty?
|
|
82
|
+
find_min(@root).val
|
|
83
|
+
end
|
|
42
84
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
85
|
+
# Returns the maximum value in the tree.
|
|
86
|
+
#
|
|
87
|
+
# @return [Comparable] the maximum value
|
|
88
|
+
# @raise [IndexError] if the tree is empty
|
|
89
|
+
# @example
|
|
90
|
+
# bst.insert(5).insert(3).insert(7)
|
|
91
|
+
# bst.max # => 7
|
|
92
|
+
def max
|
|
93
|
+
raise IndexError, "tree is empty" if empty?
|
|
94
|
+
find_max(@root).val
|
|
95
|
+
end
|
|
49
96
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
97
|
+
# Returns an array of values in inorder traversal (left, root, right).
|
|
98
|
+
#
|
|
99
|
+
# @return [Array<Comparable>] values in inorder sequence (sorted order)
|
|
100
|
+
# @example
|
|
101
|
+
# bst.insert(5).insert(3).insert(7)
|
|
102
|
+
# bst.inorder # => [3, 5, 7]
|
|
103
|
+
def inorder
|
|
104
|
+
return [] if empty?
|
|
105
|
+
result = []
|
|
106
|
+
traverse_inorder(@root, result)
|
|
107
|
+
result
|
|
108
|
+
end
|
|
56
109
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
110
|
+
# Returns an array of values in preorder traversal (root, left, right).
|
|
111
|
+
#
|
|
112
|
+
# @return [Array<Comparable>] values in preorder sequence
|
|
113
|
+
# @example
|
|
114
|
+
# bst.insert(5).insert(3).insert(7)
|
|
115
|
+
# bst.preorder # => [5, 3, 7]
|
|
116
|
+
def preorder
|
|
117
|
+
return [] if empty?
|
|
118
|
+
result = []
|
|
119
|
+
traverse_preorder(@root, result)
|
|
120
|
+
result
|
|
121
|
+
end
|
|
60
122
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
123
|
+
# Returns an array of values in postorder traversal (left, right, root).
|
|
124
|
+
#
|
|
125
|
+
# @return [Array<Comparable>] values in postorder sequence
|
|
126
|
+
# @example
|
|
127
|
+
# bst.insert(5).insert(3).insert(7)
|
|
128
|
+
# bst.postorder # => [3, 7, 5]
|
|
129
|
+
def postorder
|
|
130
|
+
return [] if empty?
|
|
131
|
+
result = []
|
|
132
|
+
traverse_postorder(@root, result)
|
|
133
|
+
result
|
|
134
|
+
end
|
|
64
135
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
136
|
+
# Returns the number of elements in the tree.
|
|
137
|
+
#
|
|
138
|
+
# @return [Integer] the number of elements
|
|
139
|
+
# @example
|
|
140
|
+
# bst.insert(5).insert(3)
|
|
141
|
+
# bst.size # => 2
|
|
142
|
+
def size
|
|
143
|
+
@size
|
|
144
|
+
end
|
|
68
145
|
|
|
69
|
-
|
|
146
|
+
# Checks if the tree is empty.
|
|
147
|
+
#
|
|
148
|
+
# @return [Boolean] true if the tree contains no elements
|
|
149
|
+
# @example
|
|
150
|
+
# bst = DSA::BinarySearchTree.new
|
|
151
|
+
# bst.empty? # => true
|
|
152
|
+
def empty?
|
|
153
|
+
@size == 0
|
|
154
|
+
end
|
|
70
155
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
156
|
+
# Returns a defensive copy of the tree as an array (inorder traversal).
|
|
157
|
+
#
|
|
158
|
+
# @return [Array<Comparable>] an array of values in sorted order
|
|
159
|
+
# @example
|
|
160
|
+
# bst.insert(5).insert(3).insert(7)
|
|
161
|
+
# bst.to_a # => [3, 5, 7]
|
|
162
|
+
def to_a
|
|
163
|
+
inorder
|
|
164
|
+
end
|
|
75
165
|
|
|
76
|
-
|
|
77
|
-
node.left, added = insert_recursive(node.left, val)
|
|
78
|
-
elsif val > node.val
|
|
79
|
-
node.right, added = insert_recursive(node.right, val)
|
|
80
|
-
else
|
|
81
|
-
added = false
|
|
82
|
-
end
|
|
166
|
+
private
|
|
83
167
|
|
|
84
|
-
|
|
168
|
+
# Recursively inserts a value into the tree.
|
|
169
|
+
#
|
|
170
|
+
# @param node [Node, nil] the current node being examined
|
|
171
|
+
# @param val [Comparable] the value to insert
|
|
172
|
+
# @return [Array] tuple of (updated node, whether a new node was added)
|
|
173
|
+
def insert_recursive(node, val)
|
|
174
|
+
if node.nil?
|
|
175
|
+
return [Node.new(val: val, left: nil, right: nil), true]
|
|
85
176
|
end
|
|
86
177
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
else
|
|
94
|
-
find_node(node.right, val)
|
|
95
|
-
end
|
|
178
|
+
if val < node.val
|
|
179
|
+
node.left, added = insert_recursive(node.left, val)
|
|
180
|
+
elsif val > node.val
|
|
181
|
+
node.right, added = insert_recursive(node.right, val)
|
|
182
|
+
else
|
|
183
|
+
added = false
|
|
96
184
|
end
|
|
97
185
|
|
|
98
|
-
|
|
99
|
-
|
|
186
|
+
[node, added]
|
|
187
|
+
end
|
|
100
188
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
189
|
+
# Finds a node with the given value.
|
|
190
|
+
#
|
|
191
|
+
# @param node [Node, nil] the current node being examined
|
|
192
|
+
# @param val [Comparable] the value to find
|
|
193
|
+
# @return [Node, nil] the node if found, nil otherwise
|
|
194
|
+
def find_node(node, val)
|
|
195
|
+
return nil unless node
|
|
196
|
+
return node if node.val == val
|
|
109
197
|
|
|
110
|
-
|
|
198
|
+
if val < node.val
|
|
199
|
+
find_node(node.left, val)
|
|
200
|
+
else
|
|
201
|
+
find_node(node.right, val)
|
|
111
202
|
end
|
|
203
|
+
end
|
|
112
204
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
205
|
+
# Recursively deletes a value from the tree.
|
|
206
|
+
#
|
|
207
|
+
# @param node [Node, nil] the current node being examined
|
|
208
|
+
# @param val [Comparable] the value to delete
|
|
209
|
+
# @return [Array] tuple of (updated node, whether the value was deleted)
|
|
210
|
+
def delete_recursive(node, val)
|
|
211
|
+
return [nil, false] unless node
|
|
116
212
|
|
|
117
|
-
|
|
118
|
-
node.
|
|
119
|
-
|
|
120
|
-
node
|
|
213
|
+
if val < node.val
|
|
214
|
+
node.left, deleted = delete_recursive(node.left, val)
|
|
215
|
+
elsif val > node.val
|
|
216
|
+
node.right, deleted = delete_recursive(node.right, val)
|
|
217
|
+
else
|
|
218
|
+
deleted = true
|
|
219
|
+
return [delete_node(node), true]
|
|
121
220
|
end
|
|
122
221
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
node
|
|
126
|
-
end
|
|
222
|
+
[node, deleted]
|
|
223
|
+
end
|
|
127
224
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
225
|
+
# Handles the three cases for node deletion.
|
|
226
|
+
#
|
|
227
|
+
# @param node [Node] the node to delete
|
|
228
|
+
# @return [Node, nil] the replacement node
|
|
229
|
+
def delete_node(node)
|
|
230
|
+
return node.right unless node.left
|
|
231
|
+
return node.left unless node.right
|
|
132
232
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
end
|
|
233
|
+
successor = find_min(node.right)
|
|
234
|
+
node.val = successor.val
|
|
235
|
+
node.right, _ = delete_recursive(node.right, successor.val)
|
|
236
|
+
node
|
|
237
|
+
end
|
|
139
238
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
239
|
+
# Finds the node with the minimum value in a subtree.
|
|
240
|
+
#
|
|
241
|
+
# @param node [Node] the root of the subtree
|
|
242
|
+
# @return [Node] the node with the minimum value
|
|
243
|
+
def find_min(node)
|
|
244
|
+
node = node.left while node.left
|
|
245
|
+
node
|
|
246
|
+
end
|
|
146
247
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
248
|
+
# Finds the node with the maximum value in a subtree.
|
|
249
|
+
#
|
|
250
|
+
# @param node [Node] the root of the subtree
|
|
251
|
+
# @return [Node] the node with the maximum value
|
|
252
|
+
def find_max(node)
|
|
253
|
+
node = node.right while node.right
|
|
254
|
+
node
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# Recursively traverses the tree in inorder.
|
|
258
|
+
#
|
|
259
|
+
# @param node [Node, nil] the current node
|
|
260
|
+
# @param result [Array] the array to accumulate values
|
|
261
|
+
def traverse_inorder(node, result)
|
|
262
|
+
return unless node
|
|
263
|
+
traverse_inorder(node.left, result)
|
|
264
|
+
result << node.val
|
|
265
|
+
traverse_inorder(node.right, result)
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# Recursively traverses the tree in preorder.
|
|
269
|
+
#
|
|
270
|
+
# @param node [Node, nil] the current node
|
|
271
|
+
# @param result [Array] the array to accumulate values
|
|
272
|
+
def traverse_preorder(node, result)
|
|
273
|
+
return unless node
|
|
274
|
+
result << node.val
|
|
275
|
+
traverse_preorder(node.left, result)
|
|
276
|
+
traverse_preorder(node.right, result)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Recursively traverses the tree in postorder.
|
|
280
|
+
#
|
|
281
|
+
# @param node [Node, nil] the current node
|
|
282
|
+
# @param result [Array] the array to accumulate values
|
|
283
|
+
def traverse_postorder(node, result)
|
|
284
|
+
return unless node
|
|
285
|
+
traverse_postorder(node.left, result)
|
|
286
|
+
traverse_postorder(node.right, result)
|
|
287
|
+
result << node.val
|
|
153
288
|
end
|
|
154
289
|
end
|
data/lib/dsa-ruby/deque.rb
CHANGED
|
@@ -1,57 +1,138 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
1
|
+
# DSA::Deque - Double-ended queue data structure.
|
|
2
|
+
#
|
|
3
|
+
# Supports efficient insertion and removal from both ends.
|
|
4
|
+
# Includes Enumerable for functional-style operations.
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# dq = DSA::Deque.new
|
|
8
|
+
# dq.push_front(1).push_back(2)
|
|
9
|
+
# dq.pop_front # => 1
|
|
10
|
+
# dq.pop_back # => 2
|
|
11
|
+
#
|
|
12
|
+
# # Enumerable support
|
|
13
|
+
# dq.push_back(1).push_back(2).push_back(3)
|
|
14
|
+
# dq.map { |x| x * 2 } # => [2, 4, 6]
|
|
15
|
+
class DSA::Deque
|
|
16
|
+
# Initialize a new empty deque.
|
|
17
|
+
#
|
|
18
|
+
# @return [DSA::Deque] a new empty deque
|
|
19
|
+
def initialize
|
|
20
|
+
@deque = []
|
|
21
|
+
@head = 0
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Inserts a value at the front of the deque.
|
|
25
|
+
#
|
|
26
|
+
# @param val [Object] the value to insert
|
|
27
|
+
# @return [DSA::Deque] self for method chaining
|
|
28
|
+
# @example
|
|
29
|
+
# dq.push_front(1).push_front(2)
|
|
30
|
+
def push_front(val)
|
|
31
|
+
@deque.unshift(val)
|
|
32
|
+
self
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Inserts a value at the back of the deque.
|
|
36
|
+
#
|
|
37
|
+
# @param val [Object] the value to insert
|
|
38
|
+
# @return [DSA::Deque] self for method chaining
|
|
39
|
+
# @example
|
|
40
|
+
# dq.push_back(1).push_back(2)
|
|
41
|
+
def push_back(val)
|
|
42
|
+
@deque.push(val)
|
|
43
|
+
self
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Removes and returns the value at the front of the deque.
|
|
47
|
+
#
|
|
48
|
+
# @return [Object] the value at the front
|
|
49
|
+
# @raise [IndexError] if the deque is empty
|
|
50
|
+
# @example
|
|
51
|
+
# dq.push_back(1).push_back(2)
|
|
52
|
+
# dq.pop_front # => 1
|
|
53
|
+
def pop_front
|
|
54
|
+
raise IndexError, "deque is empty" if empty?
|
|
55
|
+
@deque.shift
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Removes and returns the value at the back of the deque.
|
|
59
|
+
#
|
|
60
|
+
# @return [Object] the value at the back
|
|
61
|
+
# @raise [IndexError] if the deque is empty
|
|
62
|
+
# @example
|
|
63
|
+
# dq.push_back(1).push_back(2)
|
|
64
|
+
# dq.pop_back # => 2
|
|
65
|
+
def pop_back
|
|
66
|
+
raise IndexError, "deque is empty" if empty?
|
|
67
|
+
@deque.pop
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Returns the value at the front of the deque without removing it.
|
|
71
|
+
#
|
|
72
|
+
# @return [Object] the value at the front
|
|
73
|
+
# @raise [IndexError] if the deque is empty
|
|
74
|
+
# @example
|
|
75
|
+
# dq.push_back(1).push_back(2)
|
|
76
|
+
# dq.front # => 1
|
|
77
|
+
def front
|
|
78
|
+
raise IndexError, "deque is empty" if empty?
|
|
79
|
+
@deque.first
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Returns the value at the back of the deque without removing it.
|
|
83
|
+
#
|
|
84
|
+
# @return [Object] the value at the back
|
|
85
|
+
# @raise [IndexError] if the deque is empty
|
|
86
|
+
# @example
|
|
87
|
+
# dq.push_back(1).push_back(2)
|
|
88
|
+
# dq.back # => 2
|
|
89
|
+
def back
|
|
90
|
+
raise IndexError, "deque is empty" if empty?
|
|
91
|
+
@deque.last
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Returns the number of elements in the deque.
|
|
95
|
+
#
|
|
96
|
+
# @return [Integer] the number of elements
|
|
97
|
+
# @example
|
|
98
|
+
# dq.push_back(1).push_back(2)
|
|
99
|
+
# dq.size # => 2
|
|
100
|
+
def size
|
|
101
|
+
@deque.size
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Checks if the deque is empty.
|
|
105
|
+
#
|
|
106
|
+
# @return [Boolean] true if the deque contains no elements
|
|
107
|
+
# @example
|
|
108
|
+
# dq = DSA::Deque.new
|
|
109
|
+
# dq.empty? # => true
|
|
110
|
+
def empty?
|
|
111
|
+
@deque.empty?
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Returns a defensive copy of the deque as an array.
|
|
115
|
+
#
|
|
116
|
+
# @return [Array] an array containing all elements (front to back order)
|
|
117
|
+
# @example
|
|
118
|
+
# dq.push_back(1).push_back(2).push_back(3)
|
|
119
|
+
# dq.to_a # => [1, 2, 3]
|
|
120
|
+
def to_a
|
|
121
|
+
@deque.dup
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Includes Enumerable for functional-style operations like map, select, etc.
|
|
125
|
+
include Enumerable
|
|
126
|
+
|
|
127
|
+
# Yields each element in the deque from front to back.
|
|
128
|
+
#
|
|
129
|
+
# @yield [val] yields each value to the block
|
|
130
|
+
# @return [Enumerator] if no block given
|
|
131
|
+
# @example
|
|
132
|
+
# dq.push_back(1).push_back(2).push_back(3)
|
|
133
|
+
# dq.each { |x| puts x } # prints 1, 2, 3
|
|
134
|
+
def each(&block)
|
|
135
|
+
return enum_for(:each) unless block_given?
|
|
136
|
+
@deque.each(&block)
|
|
56
137
|
end
|
|
57
138
|
end
|