(array, k, left = 0, right = Infinity, compare)
| 877 | // Based on https://github.com/mourner/quickselect |
| 878 | // ISC license, Copyright 2018 Vladimir Agafonkin. |
| 879 | function quickselect(array, k, left = 0, right = Infinity, compare) { |
| 880 | k = Math.floor(k); |
| 881 | left = Math.floor(Math.max(0, left)); |
| 882 | right = Math.floor(Math.min(array.length - 1, right)); |
| 883 | |
| 884 | if (!(left <= k && k <= right)) return array; |
| 885 | |
| 886 | compare = compare === undefined ? ascendingDefined : compareDefined(compare); |
| 887 | |
| 888 | while (right > left) { |
| 889 | if (right - left > 600) { |
| 890 | const n = right - left + 1; |
| 891 | const m = k - left + 1; |
| 892 | const z = Math.log(n); |
| 893 | const s = 0.5 * Math.exp(2 * z / 3); |
| 894 | const sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1); |
| 895 | const newLeft = Math.max(left, Math.floor(k - m * s / n + sd)); |
| 896 | const newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd)); |
| 897 | quickselect(array, k, newLeft, newRight, compare); |
| 898 | } |
| 899 | |
| 900 | const t = array[k]; |
| 901 | let i = left; |
| 902 | let j = right; |
| 903 | |
| 904 | swap$1(array, left, k); |
| 905 | if (compare(array[right], t) > 0) swap$1(array, left, right); |
| 906 | |
| 907 | while (i < j) { |
| 908 | swap$1(array, i, j), ++i, --j; |
| 909 | while (compare(array[i], t) < 0) ++i; |
| 910 | while (compare(array[j], t) > 0) --j; |
| 911 | } |
| 912 | |
| 913 | if (compare(array[left], t) === 0) swap$1(array, left, j); |
| 914 | else ++j, swap$1(array, j, right); |
| 915 | |
| 916 | if (j <= k) left = j + 1; |
| 917 | if (k <= j) right = j - 1; |
| 918 | } |
| 919 | |
| 920 | return array; |
| 921 | } |
| 922 | |
| 923 | function swap$1(array, i, j) { |
| 924 | const t = array[i]; |
no test coverage detected