Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function mergeSort(comparator, inPlace = false) {
- const original = this;
- const n = original?.length >>> 0;
- if (!original || typeof original !== 'object')
- throw new TypeError('mergeSort must be called on an array-like object');
- if (!Number.isFinite(n) || n < 0)
- throw new TypeError('Invalid length on array-like object');
- if (typeof comparator !== 'function' && comparator != null)
- throw new TypeError('Comparator must be a function');
- if (inPlace && Object.isFrozen(original))
- throw new TypeError('Cannot sort in-place a frozen object');
- if (n < 2) return inPlace ? original : original.constructor.from(original);
- const smartComparator = (a, b) => {
- if (a === b) return 0;
- if (a == null) return -1;
- if (b == null) return 1;
- if (typeof a === 'number' && typeof b === 'number') return a - b;
- if (typeof a === 'string' && typeof b === 'string') return a.localeCompare(b);
- if (typeof a === 'boolean' && typeof b === 'boolean') return a - b;
- try {
- const va = a.valueOf?.(), vb = b.valueOf?.();
- if (typeof va === 'number' && typeof vb === 'number') return va - vb;
- if (typeof va === 'string' && typeof vb === 'string') return va.localeCompare(vb);
- } catch {}
- try {
- return String(a).localeCompare(String(b));
- } catch {}
- throw new TypeError(Cannot compare values: ${a} and ${b});
- };
- const cmp = comparator ?? smartComparator;
- const arr = inPlace ? original : [...original];
- const buffer = new Array(n);
- const threshold = 32;
- function insertionSort(start, end) {
- for (let i = start + 1; i < end; i++) {
- const temp = arr[i];
- let j = i - 1;
- while (j >= start && cmp(arr[j], temp) > 0) {
- arr[j + 1] = arr[j--];
- }
- arr[j + 1] = temp;
- }
- }
- function merge(start, mid, end) {
- let i = start, j = mid, k = start;
- while (i < mid && j < end) {
- buffer[k++] = cmp(arr[i], arr[j]) <= 0 ? arr[i++] : arr[j++];
- }
- while (i < mid) buffer[k++] = arr[i++];
- while (j < end) buffer[k++] = arr[j++];
- for (let m = start; m < end; m++) arr[m] = buffer[m];
- }
- function sort(start, end) {
- const size = end - start;
- if (size <= threshold) {
- insertionSort(start, end);
- return;
- }
- const mid = (start + end) >>> 1;
- sort(start, mid);
- sort(mid, end);
- if (cmp(arr[mid - 1], arr[mid]) <= 0) return; // skip merge if already sorted
- merge(start, mid, end);
- }
- sort(0, n);
- return inPlace ? original : original.constructor.from(arr);
- }
Advertisement
Add Comment
Please, Sign In to add comment