io-event 1.13.0 → 1.14.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a32ca73de2138ec23628217095bdfd7414f9b898e2af962922e449b297b20821
4
- data.tar.gz: 67d4d9f80ec4195efdda39dc71ed5c84772336bcf1701d691115212143fd6912
3
+ metadata.gz: 53a9942daf957580fe332adea530a3bba659c0ec5405560078233ead0b893d11
4
+ data.tar.gz: d6eea90381836e4f1bf62430ae95ea0f7f2b1693683d2a114b5193f0c7a1d3f8
5
5
  SHA512:
6
- metadata.gz: 12e19eb71a5f491b3513f2506474e2b184e9b4231e70cd9282b8ebdb38a214133c2d1b4fdf77d1a502c2758b29b1fe2160f55b47e060e6cd24fe36a5ed646405
7
- data.tar.gz: 6ad9a898bb51eea78a28160b1d12ba8ffea073842971741c264ffad4f71e96d722289ebd840f5a2f365361926e98819b4e45014860dc4cd1eaa0f96c4fd540a1
6
+ metadata.gz: 9bfd04d670380038ec6a57a212f0f927b3fd748f93ac95c26e04adb1ed829a999fc02ebca56a27812c84be402b9fef576ba5d53be0df7b8f5e06bb516c70f2b6
7
+ data.tar.gz: ca71eac94412be0bbb953d32eb60ef1654fe24535012bc3f6f9a1a5375377175a71641c28e5ab92a5f3d44418ab50c3ef177a552cc0abe57f633e718cb2b4bc4
checksums.yaml.gz.sig CHANGED
Binary file
@@ -79,19 +79,112 @@ class IO
79
79
  return self
80
80
  end
81
81
 
82
+ # Add multiple elements to the heap efficiently in O(n) time.
83
+ # This is more efficient than calling push multiple times (O(n log n)).
84
+ #
85
+ # @parameter elements [Array] The elements to add to the heap.
86
+ # @returns [self] Returns self for method chaining.
87
+ def concat(elements)
88
+ return self if elements.empty?
89
+
90
+ # Add all elements to the array without maintaining heap property - O(n)
91
+ @contents.concat(elements)
92
+
93
+ # Rebuild the heap property for the entire array - O(n)
94
+ heapify!
95
+
96
+ return self
97
+ end
98
+
82
99
  # Empties out the heap, discarding all elements
83
100
  def clear!
84
101
  @contents = []
85
102
  end
86
103
 
104
+ # Remove a specific element from the heap.
105
+ #
106
+ # O(n) where n is the number of elements in the heap.
107
+ #
108
+ # @parameter element [Object] The element to remove.
109
+ # @returns [Object | Nil] The removed element, or nil if not found.
110
+ def delete(element)
111
+ # Find the index of the element - O(n) linear search
112
+ index = @contents.index(element)
113
+ return nil unless index
114
+
115
+ # If it's the last element, just remove it
116
+ if index == @contents.size - 1
117
+ return @contents.pop
118
+ end
119
+
120
+ # Store the value we're removing
121
+ removed_value = @contents[index]
122
+
123
+ # Replace with the last element
124
+ last = @contents.pop
125
+ @contents[index] = last
126
+
127
+ # Restore heap property - might need to bubble up or down
128
+ if index > 0 && @contents[index] < @contents[(index - 1) / 2]
129
+ # New element is smaller than parent, bubble up
130
+ bubble_up(index)
131
+ else
132
+ # New element might be larger than children, bubble down
133
+ bubble_down(index)
134
+ end
135
+
136
+ # validate!
137
+
138
+ return removed_value
139
+ end
140
+
141
+ # Remove elements matching the given block condition by rebuilding the heap.
142
+ #
143
+ # This is more efficient than multiple delete operations when removing many elements.
144
+ #
145
+ # O(n) where n is the number of elements in the heap.
146
+ #
147
+ # @yields [Object] Each element in the heap for testing
148
+ # @returns [Integer] The number of elements removed
149
+ def delete_if
150
+ return enum_for(:delete_if) unless block_given?
151
+
152
+ original_size = @contents.size
153
+
154
+ # Filter out elements that match the condition - O(n)
155
+ @contents.reject! {|element| yield(element)}
156
+
157
+ # If we removed elements, rebuild the heap - O(n)
158
+ if @contents.size < original_size
159
+ heapify!
160
+ end
161
+
162
+ # Return number of elements removed
163
+ original_size - @contents.size
164
+ end
165
+
87
166
  # Validate the heap invariant. Every element except the root must not be smaller than its parent element. Note that it MAY be equal.
88
167
  def valid?
89
- # Notice we skip index 0 on purpose, because it has no parent
168
+ # Notice we skip index 0 on purpose, because it has no parent:
90
169
  (1..(@contents.size - 1)).all? {|index| @contents[index] >= @contents[(index - 1) / 2]}
91
170
  end
92
171
 
93
172
  private
94
173
 
174
+ # Rebuild the heap property from an arbitrary array in O(n) time.
175
+ # Uses bottom-up heapify algorithm starting from the last non-leaf node.
176
+ def heapify!
177
+ return if @contents.size <= 1
178
+
179
+ # Start from the last non-leaf node and work backwards to root:
180
+ last_non_leaf_index = (@contents.size / 2) - 1
181
+ last_non_leaf_index.downto(0) do |index|
182
+ bubble_down(index)
183
+ end
184
+
185
+ # validate!
186
+ end
187
+
95
188
  # Left here for reference, but unused.
96
189
  # def swap(i, j)
97
190
  # @contents[i], @contents[j] = @contents[j], @contents[i]
@@ -7,6 +7,6 @@
7
7
  class IO
8
8
  # @namespace
9
9
  module Event
10
- VERSION = "1.13.0"
10
+ VERSION = "1.14.0"
11
11
  end
12
12
  end
data/readme.md CHANGED
@@ -18,6 +18,10 @@ Please see the [project documentation](https://socketry.github.io/io-event/) for
18
18
 
19
19
  Please see the [project releases](https://socketry.github.io/io-event/releases/index) for all releases.
20
20
 
21
+ ### v1.14.0
22
+
23
+ - [Enhanced `IO::Event::PriorityHeap` with deletion and bulk insertion methods](https://socketry.github.io/io-event/releases/index#enhanced-io::event::priorityheap-with-deletion-and-bulk-insertion-methods)
24
+
21
25
  ### v1.11.2
22
26
 
23
27
  - Fix Windows build.
data/releases.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # Releases
2
2
 
3
+ ## v1.14.0
4
+
5
+ ### Enhanced `IO::Event::PriorityHeap` with deletion and bulk insertion methods
6
+
7
+ The {ruby IO::Event::PriorityHeap} now supports efficient element removal and bulk insertion:
8
+
9
+ - **`delete(element)`**: Remove a specific element from the heap in O(n) time
10
+ - **`delete_if(&block)`**: Remove elements matching a condition with O(n) amortized bulk deletion
11
+ - **`concat(elements)`**: Add multiple elements efficiently in O(n) time
12
+
13
+ <!-- end list -->
14
+
15
+ ``` ruby
16
+ heap = IO::Event::PriorityHeap.new
17
+
18
+ # Efficient bulk insertion - O(n) instead of O(n log n)
19
+ heap.concat([5, 2, 8, 1, 9, 3])
20
+
21
+ # Remove specific element
22
+ removed = heap.delete(5) # Returns 5, heap maintains order
23
+
24
+ # Bulk removal with condition
25
+ count = heap.delete_if { |x| x.even? } # Removes 2, 8 efficiently
26
+ ```
27
+
28
+ The `delete_if` and `concat` methods are particularly efficient for bulk operations, using bottom-up heapification to maintain the heap property in O(n) time. This provides significant performance improvements:
29
+
30
+ - **Bulk insertion**: O(n log n) → O(n) for adding multiple elements
31
+ - **Bulk deletion**: O(k×n) → O(n) for removing k elements
32
+
33
+ Both methods maintain the heap invariant and include comprehensive test coverage with edge case validation.
34
+
3
35
  ## v1.11.2
4
36
 
5
37
  - Fix Windows build.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: io-event
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.13.0
4
+ version: 1.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -116,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0'
118
118
  requirements: []
119
- rubygems_version: 3.6.9
119
+ rubygems_version: 3.7.0.dev
120
120
  specification_version: 4
121
121
  summary: An event loop.
122
122
  test_files: []
metadata.gz.sig CHANGED
Binary file