穩固排序
穩固排序是指,假如原數組中有多個元素是“相稱的”,那末這些元素在排序后數組的相對遞次應當堅持穩定。
比方:我們對{name:string, age:number}[]
數組用age舉行排序,有許多人是25歲,那末在排序后的數組中,這些25歲的人應當根據它們【在原數組中湧現的遞次】來分列。
原生的sort是不一定是穩固的,由於差別的引擎完成差別,比方V8的sort就用到快排,快排不是穩固的排序。
為何須要穩固的排序?个中一種狀況是:原列表已在某個字段上排好序,然而要排序的字段上可能有許多項是“相稱”的。
比方有一個{name:string, age:number}[]
數組,它【已在name上根據字母遞次排好序】了,如今願望根據age來排序。假設有許多人的age是25,假如排序是穩固的話,就可以保證這些25歲的人【在輸出列表中是根據字母遞次分列的】,如許的話輸出的列表會悅目許多。
完成
typescript
/**
* @description 合併排序(穩固排序)。
* 此要領會轉變原數組,假如不想損壞原數組,調用者本身建立數組副本作為參數。
*/
function mergeSort<T>(arr: T[], compare: (a: T, b: T) => -1 | 0 | 1): T[] {
if (!Array.isArray(arr)) {
throw new Error('mergeSort的參數必需為數組');
}
_ms(arr, compare, 0, arr.length);
return arr;
}
/**
* @description 排序局限:[begin, end)
*/
function _ms<T>(arr: T[], compare: (a: T, b: T) => -1 | 0 | 1, begin: number, end: number): void {
const size = end - begin;
if (size <= 1) { return; }
// tslint:disable-next-line: no-bitwise
const middle = (end + begin) >> 1;
_ms(arr, compare, begin, middle);
_ms(arr, compare, middle, end);
if (compare(arr[middle - 1], arr[middle]) <= 0) { return; } // 遞次已準確
const merged = [];
let leftIndex = begin, rightIndex = middle;
while (merged.length < size) {
if (leftIndex === middle) {
merged.push(arr[rightIndex++]);
} else if (rightIndex === end) {
merged.push(arr[leftIndex++]);
} else {
const c = compare(arr[leftIndex], arr[rightIndex]);
if (c <= 0) {
merged.push(arr[leftIndex++]);
} else {
merged.push(arr[rightIndex++]);
}
}
}
arr.splice(begin, size, ...merged);
}
JavaScript
/**
* @description 合併排序(穩固排序)。
* 此要領會轉變原數組,假如不想損壞原數組,調用者本身建立數組副本作為參數。
*/
function mergeSort(arr, compare) {
if (!Array.isArray(arr)) {
throw new Error('mergeSort的參數必需為數組');
}
_ms(arr, compare, 0, arr.length);
return arr;
}
/**
* @description 排序局限:[begin, end)
*/
function _ms(arr, compare, begin, end) {
var size = end - begin;
if (size <= 1) {
return;
}
// tslint:disable-next-line: no-bitwise
var middle = (end + begin) >> 1;
_ms(arr, compare, begin, middle);
_ms(arr, compare, middle, end);
if (compare(arr[middle - 1], arr[middle]) <= 0) { return; } // 遞次已準確
var merged = [];
var leftIndex = begin, rightIndex = middle;
while (merged.length < size) {
if (leftIndex === middle) {
merged.push(arr[rightIndex++]);
}
else if (rightIndex === end) {
merged.push(arr[leftIndex++]);
}
else {
var c = compare(arr[leftIndex], arr[rightIndex]);
if (c <= 0) {
merged.push(arr[leftIndex++]);
}
else {
merged.push(arr[rightIndex++]);
}
}
}
arr.splice(begin, size, ...merged);
}
測試
去leetcode上找一道能用排序的題測試,比方75. Sort Colors(雖然說這道題不必排序效力更高)。