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.
@@ -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
- module DSA
2
- class PriorityQueue
3
- def initialize(type: :min)
4
- @heap = type == :min ? MinHeap.new : MaxHeap.new
5
- end
6
-
7
- def push(item, priority)
8
- @counter ||= 0
9
- @heap.push([priority, @counter, item])
10
- @counter += 1
11
- self
12
- end
13
-
14
- def pop
15
- raise IndexError, "priority queue is empty" if empty?
16
- _, _, item = @heap.pop
17
- item
18
- end
19
-
20
- def peek
21
- raise IndexError, "priority queue is empty" if empty?
22
- _, _, item = @heap.peek
23
- item
24
- end
25
-
26
- def priority_peek
27
- raise IndexError, "priority queue is empty" if empty?
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
@@ -1,34 +1,80 @@
1
- module DSA
2
- class Queue
3
- def initialize
4
- @elements = []
5
- end
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
- def enqueue(val)
8
- @elements.push(val)
9
- self
10
- end
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
- def dequeue
13
- raise IndexError, "queue is empty" if empty?
14
- @elements.shift
15
- end
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
- def peek
18
- raise IndexError, "queue is empty" if empty?
19
- @elements.first
20
- end
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
- def size
23
- @elements.size
24
- end
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
- def empty?
27
- @elements.empty?
28
- end
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
- def to_a
31
- @elements.dup
32
- end
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