@@ -9,10 +9,8 @@ heap implementations).
9
9
package quickselect
10
10
11
11
import (
12
- "container/heap"
13
- "errors"
14
12
"fmt"
15
- "math/rand"
13
+ "math/rand/v2 "
16
14
)
17
15
18
16
const (
@@ -152,7 +150,7 @@ func randomizedSelectionFinding(data Interface, low, high, k int) {
152
150
return
153
151
}
154
152
155
- pivotIndex = rand .Intn (high + 1 - low ) + low
153
+ pivotIndex = rand .IntN (high + 1 - low ) + low
156
154
pivotIndex = partition (data , low , high , pivotIndex )
157
155
158
156
if k < pivotIndex {
@@ -186,7 +184,8 @@ func naiveSelectionFinding(data Interface, k int) {
186
184
}
187
185
resetLargestIndex (smallestIndices , data )
188
186
189
- for i := k ; i < data .Len (); i ++ {
187
+ length := data .Len ()
188
+ for i := k ; i < length ; i ++ {
190
189
if data .Less (i , smallestIndices [k - 1 ]) {
191
190
smallestIndices [k - 1 ] = i
192
191
resetLargestIndex (smallestIndices , data )
@@ -239,27 +238,30 @@ func partition(data Interface, low, high, pivotIndex int) int {
239
238
return partitionIndex
240
239
}
241
240
242
- type dataHeap struct {
243
- heapIndices []int
244
- data Interface
245
- }
246
-
247
- func (h dataHeap ) Len () int { return len (h .heapIndices ) }
248
- func (h dataHeap ) Less (i , j int ) bool { return h .data .Less (h .heapIndices [j ], h .heapIndices [i ]) }
249
- func (h dataHeap ) Swap (i , j int ) {
250
- h .heapIndices [i ], h .heapIndices [j ] = h .heapIndices [j ], h .heapIndices [i ]
251
- }
252
-
253
- func (h * dataHeap ) Push (x interface {}) {
254
- h .heapIndices = append (h .heapIndices , x .(int ))
241
+ func heapInit (data Interface , heap []int ) {
242
+ // Heapify process
243
+ n := len (heap )
244
+ for i := n / 2 - 1 ; i >= 0 ; i -- {
245
+ heapDown (data , heap , i , n )
246
+ }
255
247
}
256
248
257
- func (h * dataHeap ) Pop () interface {} {
258
- old := h .heapIndices
259
- n := len (old )
260
- x := old [n - 1 ]
261
- h .heapIndices = old [0 : n - 1 ]
262
- return x
249
+ func heapDown (data Interface , heap []int , i , n int ) {
250
+ for {
251
+ j1 := 2 * i + 1
252
+ if j1 >= n || j1 < 0 { // j1 < 0 after int overflow
253
+ break
254
+ }
255
+ j := j1 // left child
256
+ if j2 := j1 + 1 ; j2 < n && data .Less (heap [j1 ], heap [j2 ]) {
257
+ j = j2 // right child
258
+ }
259
+ if ! data .Less (heap [i ], heap [j ]) {
260
+ break
261
+ }
262
+ heap [i ], heap [j ] = heap [j ], heap [i ]
263
+ i = j
264
+ }
263
265
}
264
266
265
267
/*
@@ -268,26 +270,23 @@ It keeps a max-heap of the smallest k elements seen so far as we iterate over
268
270
all of the elements. It adds a new element and pops the largest element.
269
271
*/
270
272
func heapSelectionFinding (data Interface , k int ) {
271
- heapIndices := make ([]int , k )
273
+ heap := make ([]int , k )
272
274
for i := 0 ; i < k ; i ++ {
273
- heapIndices [i ] = i
275
+ heap [i ] = i
274
276
}
277
+ heapInit (data , heap )
275
278
276
- h := & dataHeap {heapIndices , data }
277
- heap .Init (h )
278
- var currentHeapMax int
279
- for i := k ; i < data .Len (); i ++ {
280
- currentHeapMax = h .heapIndices [0 ]
281
-
282
- if data .Less (i , currentHeapMax ) {
283
- heap .Push (h , i )
284
- heap .Pop (h )
279
+ length := data .Len ()
280
+ for i := k ; i < length ; i ++ {
281
+ if data .Less (i , heap [0 ]) {
282
+ heap [0 ] = i
283
+ heapDown (data , heap , 0 , k )
285
284
}
286
285
}
287
286
288
- insertionSort (IntSlice (h . heapIndices ), 0 , len ( h . heapIndices ) )
289
- for i := 0 ; i < len ( h . heapIndices ) ; i ++ {
290
- data .Swap (i , h . heapIndices [i ])
287
+ insertionSort (IntSlice (heap ), 0 , k )
288
+ for i := 0 ; i < k ; i ++ {
289
+ data .Swap (i , heap [i ])
291
290
}
292
291
}
293
292
@@ -306,8 +305,7 @@ method will raise an error.
306
305
func QuickSelect (data Interface , k int ) error {
307
306
length := data .Len ()
308
307
if k < 1 || k > length {
309
- message := fmt .Sprintf ("The specified index '%d' is outside of the data's range of indices [0,%d)" , k , length )
310
- return errors .New (message )
308
+ return fmt .Errorf ("The specified index '%d' is outside of the data's range of indices [0,%d)" , k , length )
311
309
}
312
310
313
311
kRatio := float64 (k ) / float64 (length )
0 commit comments