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
data/lib/dsa-ruby/linked_list.rb
CHANGED
|
@@ -1,17 +1,43 @@
|
|
|
1
1
|
module DSA
|
|
2
|
+
# Linked list data structures module.
|
|
3
|
+
#
|
|
4
|
+
# Provides both singly and doubly linked list implementations.
|
|
2
5
|
module LinkedList
|
|
6
|
+
# Node for a singly linked list.
|
|
7
|
+
#
|
|
8
|
+
# @!attribute [rw] val
|
|
9
|
+
# @return [Object] the value stored in the node
|
|
10
|
+
# @!attribute [rw] next
|
|
11
|
+
# @return [Node, nil] the next node in the list
|
|
3
12
|
class Node
|
|
4
13
|
attr_accessor :val, :next
|
|
5
14
|
|
|
15
|
+
# Initialize a new singly linked list node.
|
|
16
|
+
#
|
|
17
|
+
# @param val [Object] the value to store
|
|
18
|
+
# @param nxt [Node, nil] the next node (default: nil)
|
|
6
19
|
def initialize(val = 0, nxt = nil)
|
|
7
20
|
@val = val
|
|
8
21
|
@next = nxt
|
|
9
22
|
end
|
|
10
23
|
end
|
|
11
24
|
|
|
25
|
+
# Node for a doubly linked list.
|
|
26
|
+
#
|
|
27
|
+
# @!attribute [rw] val
|
|
28
|
+
# @return [Object] the value stored in the node
|
|
29
|
+
# @!attribute [rw] next
|
|
30
|
+
# @return [DoublyNode, nil] the next node in the list
|
|
31
|
+
# @!attribute [rw] prev
|
|
32
|
+
# @return [DoublyNode, nil] the previous node in the list
|
|
12
33
|
class DoublyNode
|
|
13
34
|
attr_accessor :val, :next, :prev
|
|
14
35
|
|
|
36
|
+
# Initialize a new doubly linked list node.
|
|
37
|
+
#
|
|
38
|
+
# @param val [Object] the value to store
|
|
39
|
+
# @param nxt [DoublyNode, nil] the next node (default: nil)
|
|
40
|
+
# @param prev [DoublyNode, nil] the previous node (default: nil)
|
|
15
41
|
def initialize(val = 0, nxt = nil, prev = nil)
|
|
16
42
|
@val = val
|
|
17
43
|
@next = nxt
|
|
@@ -19,18 +45,48 @@ module DSA
|
|
|
19
45
|
end
|
|
20
46
|
end
|
|
21
47
|
|
|
48
|
+
# DSA::LinkedList::Singly - Singly linked list implementation.
|
|
49
|
+
#
|
|
50
|
+
# Each node points only to the next node. Supports push (prepend),
|
|
51
|
+
# append, pop (from front), delete, find, and reverse!.
|
|
52
|
+
# Includes Enumerable for functional-style operations.
|
|
53
|
+
#
|
|
54
|
+
# @example
|
|
55
|
+
# list = DSA::LinkedList::Singly.new
|
|
56
|
+
# list.push(1).push(2).push(3)
|
|
57
|
+
# list.pop # => 3
|
|
58
|
+
# list.to_a # => [2, 1]
|
|
59
|
+
# list.reverse!
|
|
60
|
+
# list.to_a # => [1, 2]
|
|
22
61
|
class Singly
|
|
62
|
+
# Initialize a new empty singly linked list.
|
|
63
|
+
#
|
|
64
|
+
# @return [DSA::LinkedList::Singly] a new empty list
|
|
23
65
|
def initialize
|
|
24
66
|
@head = nil
|
|
25
67
|
@size = 0
|
|
26
68
|
end
|
|
27
69
|
|
|
70
|
+
# Prepends a value to the front of the list.
|
|
71
|
+
#
|
|
72
|
+
# @param val [Object] the value to prepend
|
|
73
|
+
# @return [DSA::LinkedList::Singly] self for method chaining
|
|
74
|
+
# @example
|
|
75
|
+
# list.push(2).push(1)
|
|
76
|
+
# list.to_a # => [1, 2]
|
|
28
77
|
def push(val)
|
|
29
78
|
@head = Node.new(val, @head)
|
|
30
79
|
@size += 1
|
|
31
80
|
self
|
|
32
81
|
end
|
|
33
82
|
|
|
83
|
+
# Appends a value to the end of the list.
|
|
84
|
+
#
|
|
85
|
+
# @param val [Object] the value to append
|
|
86
|
+
# @return [DSA::LinkedList::Singly] self for method chaining
|
|
87
|
+
# @example
|
|
88
|
+
# list.append(1).append(2)
|
|
89
|
+
# list.to_a # => [1, 2]
|
|
34
90
|
def append(val)
|
|
35
91
|
new_node = Node.new(val)
|
|
36
92
|
if @head.nil?
|
|
@@ -44,6 +100,13 @@ module DSA
|
|
|
44
100
|
self
|
|
45
101
|
end
|
|
46
102
|
|
|
103
|
+
# Removes and returns the value at the front of the list.
|
|
104
|
+
#
|
|
105
|
+
# @return [Object] the value at the front
|
|
106
|
+
# @raise [IndexError] if the list is empty
|
|
107
|
+
# @example
|
|
108
|
+
# list.push(1).push(2)
|
|
109
|
+
# list.pop # => 2
|
|
47
110
|
def pop
|
|
48
111
|
raise IndexError, "list is empty" unless @head
|
|
49
112
|
|
|
@@ -53,11 +116,26 @@ module DSA
|
|
|
53
116
|
val
|
|
54
117
|
end
|
|
55
118
|
|
|
119
|
+
# Returns the value at the front of the list without removing it.
|
|
120
|
+
#
|
|
121
|
+
# @return [Object] the value at the front
|
|
122
|
+
# @raise [IndexError] if the list is empty
|
|
123
|
+
# @example
|
|
124
|
+
# list.push(1).push(2)
|
|
125
|
+
# list.peek # => 2
|
|
56
126
|
def peek
|
|
57
127
|
raise IndexError, "list is empty" unless @head
|
|
58
128
|
@head.val
|
|
59
129
|
end
|
|
60
130
|
|
|
131
|
+
# Deletes the first occurrence of a value from the list.
|
|
132
|
+
#
|
|
133
|
+
# @param val [Object] the value to delete
|
|
134
|
+
# @return [Boolean] true if the value was found and deleted
|
|
135
|
+
# @example
|
|
136
|
+
# list.push(1).push(2).push(3)
|
|
137
|
+
# list.delete(2) # => true
|
|
138
|
+
# list.delete(5) # => false
|
|
61
139
|
def delete(val)
|
|
62
140
|
return false unless @head
|
|
63
141
|
|
|
@@ -80,6 +158,14 @@ module DSA
|
|
|
80
158
|
false
|
|
81
159
|
end
|
|
82
160
|
|
|
161
|
+
# Finds the first node with the given value.
|
|
162
|
+
#
|
|
163
|
+
# @param val [Object] the value to find
|
|
164
|
+
# @return [Node, nil] the node if found, nil otherwise
|
|
165
|
+
# @example
|
|
166
|
+
# list.push(1).push(2)
|
|
167
|
+
# list.find(2) # => #<Node @val=2>
|
|
168
|
+
# list.find(5) # => nil
|
|
83
169
|
def find(val)
|
|
84
170
|
node = @head
|
|
85
171
|
while node
|
|
@@ -89,6 +175,13 @@ module DSA
|
|
|
89
175
|
nil
|
|
90
176
|
end
|
|
91
177
|
|
|
178
|
+
# Reverses the list in-place.
|
|
179
|
+
#
|
|
180
|
+
# @return [DSA::LinkedList::Singly] self for method chaining
|
|
181
|
+
# @example
|
|
182
|
+
# list.push(1).push(2).push(3)
|
|
183
|
+
# list.reverse!
|
|
184
|
+
# list.to_a # => [1, 2, 3]
|
|
92
185
|
def reverse!
|
|
93
186
|
return self unless @head
|
|
94
187
|
|
|
@@ -104,14 +197,32 @@ module DSA
|
|
|
104
197
|
self
|
|
105
198
|
end
|
|
106
199
|
|
|
200
|
+
# Returns the number of elements in the list.
|
|
201
|
+
#
|
|
202
|
+
# @return [Integer] the number of elements
|
|
203
|
+
# @example
|
|
204
|
+
# list.push(1).push(2)
|
|
205
|
+
# list.size # => 2
|
|
107
206
|
def size
|
|
108
207
|
@size
|
|
109
208
|
end
|
|
110
209
|
|
|
210
|
+
# Checks if the list is empty.
|
|
211
|
+
#
|
|
212
|
+
# @return [Boolean] true if the list contains no elements
|
|
213
|
+
# @example
|
|
214
|
+
# list = DSA::LinkedList::Singly.new
|
|
215
|
+
# list.empty? # => true
|
|
111
216
|
def empty?
|
|
112
217
|
@size == 0
|
|
113
218
|
end
|
|
114
219
|
|
|
220
|
+
# Returns an array of all values in the list (front to back).
|
|
221
|
+
#
|
|
222
|
+
# @return [Array] an array of values in list order
|
|
223
|
+
# @example
|
|
224
|
+
# list.push(1).push(2).push(3)
|
|
225
|
+
# list.to_a # => [3, 2, 1]
|
|
115
226
|
def to_a
|
|
116
227
|
result = []
|
|
117
228
|
node = @head
|
|
@@ -122,8 +233,16 @@ module DSA
|
|
|
122
233
|
result
|
|
123
234
|
end
|
|
124
235
|
|
|
236
|
+
# Includes Enumerable for functional-style operations like map, select, etc.
|
|
125
237
|
include Enumerable
|
|
126
238
|
|
|
239
|
+
# Yields each value in the list from front to back.
|
|
240
|
+
#
|
|
241
|
+
# @yield [val] yields each value to the block
|
|
242
|
+
# @return [Enumerator] if no block given
|
|
243
|
+
# @example
|
|
244
|
+
# list.push(1).push(2).push(3)
|
|
245
|
+
# list.each { |x| puts x } # prints 3, 2, 1
|
|
127
246
|
def each(&block)
|
|
128
247
|
return enum_for(:each) unless block_given?
|
|
129
248
|
node = @head
|
|
@@ -134,13 +253,35 @@ module DSA
|
|
|
134
253
|
end
|
|
135
254
|
end
|
|
136
255
|
|
|
256
|
+
# DSA::LinkedList::Doubly - Doubly linked list implementation.
|
|
257
|
+
#
|
|
258
|
+
# Each node points to both the next and previous nodes.
|
|
259
|
+
# Supports push_front, push_back, pop_front, pop_back, delete, and find.
|
|
260
|
+
# Includes Enumerable for functional-style operations.
|
|
261
|
+
#
|
|
262
|
+
# @example
|
|
263
|
+
# dll = DSA::LinkedList::Doubly.new
|
|
264
|
+
# dll.push_back(1).push_back(2).push_back(3)
|
|
265
|
+
# dll.pop_front # => 1
|
|
266
|
+
# dll.pop_back # => 3
|
|
267
|
+
# dll.to_a # => [2]
|
|
137
268
|
class Doubly
|
|
269
|
+
# Initialize a new empty doubly linked list.
|
|
270
|
+
#
|
|
271
|
+
# @return [DSA::LinkedList::Doubly] a new empty list
|
|
138
272
|
def initialize
|
|
139
273
|
@head = nil
|
|
140
274
|
@tail = nil
|
|
141
275
|
@size = 0
|
|
142
276
|
end
|
|
143
277
|
|
|
278
|
+
# Inserts a value at the front of the list.
|
|
279
|
+
#
|
|
280
|
+
# @param val [Object] the value to insert
|
|
281
|
+
# @return [DSA::LinkedList::Doubly] self for method chaining
|
|
282
|
+
# @example
|
|
283
|
+
# dll.push_front(2).push_front(1)
|
|
284
|
+
# dll.to_a # => [1, 2]
|
|
144
285
|
def push_front(val)
|
|
145
286
|
node = DoublyNode.new(val, @head, nil)
|
|
146
287
|
@head.prev = node if @head
|
|
@@ -150,6 +291,13 @@ module DSA
|
|
|
150
291
|
self
|
|
151
292
|
end
|
|
152
293
|
|
|
294
|
+
# Inserts a value at the back of the list.
|
|
295
|
+
#
|
|
296
|
+
# @param val [Object] the value to insert
|
|
297
|
+
# @return [DSA::LinkedList::Doubly] self for method chaining
|
|
298
|
+
# @example
|
|
299
|
+
# dll.push_back(1).push_back(2)
|
|
300
|
+
# dll.to_a # => [1, 2]
|
|
153
301
|
def push_back(val)
|
|
154
302
|
node = DoublyNode.new(val, nil, @tail)
|
|
155
303
|
@tail.next = node if @tail
|
|
@@ -159,6 +307,13 @@ module DSA
|
|
|
159
307
|
self
|
|
160
308
|
end
|
|
161
309
|
|
|
310
|
+
# Removes and returns the value at the front of the list.
|
|
311
|
+
#
|
|
312
|
+
# @return [Object] the value at the front
|
|
313
|
+
# @raise [IndexError] if the list is empty
|
|
314
|
+
# @example
|
|
315
|
+
# dll.push_back(1).push_back(2)
|
|
316
|
+
# dll.pop_front # => 1
|
|
162
317
|
def pop_front
|
|
163
318
|
raise IndexError, "list is empty" unless @head
|
|
164
319
|
|
|
@@ -170,6 +325,13 @@ module DSA
|
|
|
170
325
|
val
|
|
171
326
|
end
|
|
172
327
|
|
|
328
|
+
# Removes and returns the value at the back of the list.
|
|
329
|
+
#
|
|
330
|
+
# @return [Object] the value at the back
|
|
331
|
+
# @raise [IndexError] if the list is empty
|
|
332
|
+
# @example
|
|
333
|
+
# dll.push_back(1).push_back(2)
|
|
334
|
+
# dll.pop_back # => 2
|
|
173
335
|
def pop_back
|
|
174
336
|
raise IndexError, "list is empty" unless @tail
|
|
175
337
|
|
|
@@ -181,16 +343,38 @@ module DSA
|
|
|
181
343
|
val
|
|
182
344
|
end
|
|
183
345
|
|
|
346
|
+
# Returns the value at the front of the list without removing it.
|
|
347
|
+
#
|
|
348
|
+
# @return [Object] the value at the front
|
|
349
|
+
# @raise [IndexError] if the list is empty
|
|
350
|
+
# @example
|
|
351
|
+
# dll.push_back(1).push_back(2)
|
|
352
|
+
# dll.front # => 1
|
|
184
353
|
def front
|
|
185
354
|
raise IndexError, "list is empty" unless @head
|
|
186
355
|
@head.val
|
|
187
356
|
end
|
|
188
357
|
|
|
358
|
+
# Returns the value at the back of the list without removing it.
|
|
359
|
+
#
|
|
360
|
+
# @return [Object] the value at the back
|
|
361
|
+
# @raise [IndexError] if the list is empty
|
|
362
|
+
# @example
|
|
363
|
+
# dll.push_back(1).push_back(2)
|
|
364
|
+
# dll.back # => 2
|
|
189
365
|
def back
|
|
190
366
|
raise IndexError, "list is empty" unless @tail
|
|
191
367
|
@tail.val
|
|
192
368
|
end
|
|
193
369
|
|
|
370
|
+
# Deletes the first occurrence of a value from the list.
|
|
371
|
+
#
|
|
372
|
+
# @param val [Object] the value to delete
|
|
373
|
+
# @return [Boolean] true if the value was found and deleted
|
|
374
|
+
# @example
|
|
375
|
+
# dll.push_back(1).push_back(2).push_back(3)
|
|
376
|
+
# dll.delete(2) # => true
|
|
377
|
+
# dll.delete(5) # => false
|
|
194
378
|
def delete(val)
|
|
195
379
|
node = @head
|
|
196
380
|
while node
|
|
@@ -207,6 +391,14 @@ module DSA
|
|
|
207
391
|
false
|
|
208
392
|
end
|
|
209
393
|
|
|
394
|
+
# Finds the first node with the given value.
|
|
395
|
+
#
|
|
396
|
+
# @param val [Object] the value to find
|
|
397
|
+
# @return [DoublyNode, nil] the node if found, nil otherwise
|
|
398
|
+
# @example
|
|
399
|
+
# dll.push_back(1).push_back(2)
|
|
400
|
+
# dll.find(2) # => #<DoublyNode @val=2>
|
|
401
|
+
# dll.find(5) # => nil
|
|
210
402
|
def find(val)
|
|
211
403
|
node = @head
|
|
212
404
|
while node
|
|
@@ -216,14 +408,32 @@ module DSA
|
|
|
216
408
|
nil
|
|
217
409
|
end
|
|
218
410
|
|
|
411
|
+
# Returns the number of elements in the list.
|
|
412
|
+
#
|
|
413
|
+
# @return [Integer] the number of elements
|
|
414
|
+
# @example
|
|
415
|
+
# dll.push_back(1).push_back(2)
|
|
416
|
+
# dll.size # => 2
|
|
219
417
|
def size
|
|
220
418
|
@size
|
|
221
419
|
end
|
|
222
420
|
|
|
421
|
+
# Checks if the list is empty.
|
|
422
|
+
#
|
|
423
|
+
# @return [Boolean] true if the list contains no elements
|
|
424
|
+
# @example
|
|
425
|
+
# dll = DSA::LinkedList::Doubly.new
|
|
426
|
+
# dll.empty? # => true
|
|
223
427
|
def empty?
|
|
224
428
|
@size == 0
|
|
225
429
|
end
|
|
226
430
|
|
|
431
|
+
# Returns an array of all values in the list (front to back).
|
|
432
|
+
#
|
|
433
|
+
# @return [Array] an array of values in list order
|
|
434
|
+
# @example
|
|
435
|
+
# dll.push_back(1).push_back(2).push_back(3)
|
|
436
|
+
# dll.to_a # => [1, 2, 3]
|
|
227
437
|
def to_a
|
|
228
438
|
result = []
|
|
229
439
|
node = @head
|
|
@@ -234,8 +444,16 @@ module DSA
|
|
|
234
444
|
result
|
|
235
445
|
end
|
|
236
446
|
|
|
447
|
+
# Includes Enumerable for functional-style operations like map, select, etc.
|
|
237
448
|
include Enumerable
|
|
238
449
|
|
|
450
|
+
# Yields each value in the list from front to back.
|
|
451
|
+
#
|
|
452
|
+
# @yield [val] yields each value to the block
|
|
453
|
+
# @return [Enumerator] if no block given
|
|
454
|
+
# @example
|
|
455
|
+
# dll.push_back(1).push_back(2).push_back(3)
|
|
456
|
+
# dll.each { |x| puts x } # prints 1, 2, 3
|
|
239
457
|
def each(&block)
|
|
240
458
|
return enum_for(:each) unless block_given?
|
|
241
459
|
node = @head
|
|
@@ -1,43 +1,109 @@
|
|
|
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
|
-
@heap.peek[0]
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def size
|
|
32
|
-
@heap.size
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def empty?
|
|
36
|
-
@heap.empty?
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
private
|
|
40
|
-
|
|
41
|
-
attr_reader :heap
|
|
1
|
+
# DSA::PriorityQueue - A priority queue data structure.
|
|
2
|
+
#
|
|
3
|
+
# Uses a heap internally to provide efficient priority-based ordering.
|
|
4
|
+
# Supports both min and max priority ordering.
|
|
5
|
+
#
|
|
6
|
+
# @example Min Priority Queue (default)
|
|
7
|
+
# pq = DSA::PriorityQueue.new(type: :min)
|
|
8
|
+
# pq.push("task_a", 3)
|
|
9
|
+
# pq.push("task_b", 1)
|
|
10
|
+
# pq.push("task_c", 2)
|
|
11
|
+
# pq.pop # => "task_b" (lowest priority value first)
|
|
12
|
+
#
|
|
13
|
+
# @example Max Priority Queue
|
|
14
|
+
# pq = DSA::PriorityQueue.new(type: :max)
|
|
15
|
+
# pq.push("task_a", 3)
|
|
16
|
+
# pq.push("task_b", 1)
|
|
17
|
+
# pq.pop # => "task_a" (highest priority value first)
|
|
18
|
+
class DSA::PriorityQueue
|
|
19
|
+
# Initialize a new priority queue.
|
|
20
|
+
#
|
|
21
|
+
# @param type [Symbol] :min for minimum priority first, :max for maximum priority first
|
|
22
|
+
# @return [DSA::PriorityQueue] a new priority queue
|
|
23
|
+
# @example
|
|
24
|
+
# DSA::PriorityQueue.new # min priority queue
|
|
25
|
+
# DSA::PriorityQueue.new(type: :max) # max priority queue
|
|
26
|
+
def initialize(type: :min)
|
|
27
|
+
@heap = type == :min ? MinHeap.new : MaxHeap.new
|
|
42
28
|
end
|
|
29
|
+
|
|
30
|
+
# Inserts an item with a given priority.
|
|
31
|
+
#
|
|
32
|
+
# @param item [Object] the item to insert
|
|
33
|
+
# @param priority [Comparable] the priority value (lower = higher priority in min queue)
|
|
34
|
+
# @return [DSA::PriorityQueue] self for method chaining
|
|
35
|
+
# @example
|
|
36
|
+
# pq.push("task", 5).push("another", 3)
|
|
37
|
+
def push(item, priority)
|
|
38
|
+
@counter ||= 0
|
|
39
|
+
@heap.push([priority, @counter, item])
|
|
40
|
+
@counter += 1
|
|
41
|
+
self
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Removes and returns the item with the highest/lowest priority.
|
|
45
|
+
#
|
|
46
|
+
# @return [Object] the item with the highest priority (max) or lowest (min)
|
|
47
|
+
# @raise [IndexError] if the priority queue is empty
|
|
48
|
+
# @example
|
|
49
|
+
# pq.push("task_a", 3)
|
|
50
|
+
# pq.push("task_b", 1)
|
|
51
|
+
# pq.pop # => "task_b"
|
|
52
|
+
def pop
|
|
53
|
+
raise IndexError, "priority queue is empty" if empty?
|
|
54
|
+
_, _, item = @heap.pop
|
|
55
|
+
item
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Returns the item with the highest/lowest priority without removing it.
|
|
59
|
+
#
|
|
60
|
+
# @return [Object] the item with the highest priority (max) or lowest (min)
|
|
61
|
+
# @raise [IndexError] if the priority queue is empty
|
|
62
|
+
# @example
|
|
63
|
+
# pq.push("task_a", 3)
|
|
64
|
+
# pq.push("task_b", 1)
|
|
65
|
+
# pq.peek # => "task_b"
|
|
66
|
+
def peek
|
|
67
|
+
raise IndexError, "priority queue is empty" if empty?
|
|
68
|
+
_, _, item = @heap.peek
|
|
69
|
+
item
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Returns the priority value of the top item without removing it.
|
|
73
|
+
#
|
|
74
|
+
# @return [Comparable] the priority value of the top item
|
|
75
|
+
# @raise [IndexError] if the priority queue is empty
|
|
76
|
+
# @example
|
|
77
|
+
# pq.push("task", 5)
|
|
78
|
+
# pq.priority_peek # => 5
|
|
79
|
+
def priority_peek
|
|
80
|
+
raise IndexError, "priority queue is empty" if empty?
|
|
81
|
+
@heap.peek[0]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Returns the number of items in the priority queue.
|
|
85
|
+
#
|
|
86
|
+
# @return [Integer] the number of items
|
|
87
|
+
# @example
|
|
88
|
+
# pq.push("task_a", 3).push("task_b", 1)
|
|
89
|
+
# pq.size # => 2
|
|
90
|
+
def size
|
|
91
|
+
@heap.size
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Checks if the priority queue is empty.
|
|
95
|
+
#
|
|
96
|
+
# @return [Boolean] true if the priority queue contains no items
|
|
97
|
+
# @example
|
|
98
|
+
# pq = DSA::PriorityQueue.new
|
|
99
|
+
# pq.empty? # => true
|
|
100
|
+
def empty?
|
|
101
|
+
@heap.empty?
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private
|
|
105
|
+
|
|
106
|
+
# @!attribute [r] heap
|
|
107
|
+
# @return [DSA::MinHeap, DSA::MaxHeap] the internal heap used for priority ordering
|
|
108
|
+
attr_reader :heap
|
|
43
109
|
end
|
data/lib/dsa-ruby/queue.rb
CHANGED
|
@@ -1,34 +1,80 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
# DSA::Queue - First-In-First-Out (FIFO) data structure.
|
|
2
|
+
#
|
|
3
|
+
# @example
|
|
4
|
+
# queue = DSA::Queue.new
|
|
5
|
+
# queue.enqueue("a").enqueue("b").enqueue("c")
|
|
6
|
+
# queue.dequeue # => "a"
|
|
7
|
+
# queue.peek # => "b"
|
|
8
|
+
class DSA::Queue
|
|
9
|
+
# Initialize a new empty queue.
|
|
10
|
+
#
|
|
11
|
+
# @return [DSA::Queue] a new empty queue
|
|
12
|
+
def initialize
|
|
13
|
+
@elements = []
|
|
14
|
+
end
|
|
6
15
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
16
|
+
# Adds a value to the back of the queue.
|
|
17
|
+
#
|
|
18
|
+
# @param val [Object] the value to add to the queue
|
|
19
|
+
# @return [DSA::Queue] self for method chaining
|
|
20
|
+
# @example Enqueue with chaining
|
|
21
|
+
# queue.enqueue("a").enqueue("b").enqueue("c")
|
|
22
|
+
def enqueue(val)
|
|
23
|
+
@elements.push(val)
|
|
24
|
+
self
|
|
25
|
+
end
|
|
11
26
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
27
|
+
# Removes and returns the value at the front of the queue.
|
|
28
|
+
#
|
|
29
|
+
# @return [Object] the value at the front of the queue
|
|
30
|
+
# @raise [IndexError] if the queue is empty
|
|
31
|
+
# @example
|
|
32
|
+
# queue.enqueue("a").enqueue("b")
|
|
33
|
+
# queue.dequeue # => "a"
|
|
34
|
+
def dequeue
|
|
35
|
+
raise IndexError, "queue is empty" if empty?
|
|
36
|
+
@elements.shift
|
|
37
|
+
end
|
|
16
38
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
39
|
+
# Returns the value at the front of the queue without removing it.
|
|
40
|
+
#
|
|
41
|
+
# @return [Object] the value at the front of the queue
|
|
42
|
+
# @raise [IndexError] if the queue is empty
|
|
43
|
+
# @example
|
|
44
|
+
# queue.enqueue("a").enqueue("b")
|
|
45
|
+
# queue.peek # => "a"
|
|
46
|
+
def peek
|
|
47
|
+
raise IndexError, "queue is empty" if empty?
|
|
48
|
+
@elements.first
|
|
49
|
+
end
|
|
21
50
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
51
|
+
# Returns the number of elements in the queue.
|
|
52
|
+
#
|
|
53
|
+
# @return [Integer] the number of elements
|
|
54
|
+
# @example
|
|
55
|
+
# queue.enqueue("a").enqueue("b")
|
|
56
|
+
# queue.size # => 2
|
|
57
|
+
def size
|
|
58
|
+
@elements.size
|
|
59
|
+
end
|
|
25
60
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
61
|
+
# Checks if the queue is empty.
|
|
62
|
+
#
|
|
63
|
+
# @return [Boolean] true if the queue contains no elements
|
|
64
|
+
# @example
|
|
65
|
+
# queue = DSA::Queue.new
|
|
66
|
+
# queue.empty? # => true
|
|
67
|
+
def empty?
|
|
68
|
+
@elements.empty?
|
|
69
|
+
end
|
|
29
70
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
71
|
+
# Returns a defensive copy of the queue as an array.
|
|
72
|
+
#
|
|
73
|
+
# @return [Array] an array containing all elements in queue order (front to back)
|
|
74
|
+
# @example
|
|
75
|
+
# queue.enqueue("a").enqueue("b").enqueue("c")
|
|
76
|
+
# queue.to_a # => ["a", "b", "c"]
|
|
77
|
+
def to_a
|
|
78
|
+
@elements.dup
|
|
33
79
|
end
|
|
34
80
|
end
|