摘要:稳定排序稳定排序是指,如果原数组中有多个元素是相等的,那么这些元素在排序后数组的相对顺序应该保持不变。实现归并排序稳定排序。的参数必须为数组排序范围顺序已经正确归并排序稳定排序。
稳定排序
稳定排序是指,如果原数组中有多个元素是“相等的”,那么这些元素在排序后数组的相对顺序应该保持不变。
比如:我们对{name:string, age:number}[]数组用age进行排序,有很多人是25岁,那么在排序后的数组中,这些25岁的人应该按照它们【在原数组中出现的顺序】来排列。
原生的sort是不一定是稳定的,因为不同的引擎实现不同,比如V8的sort就用到快排,快排不是稳定的排序。
为什么需要稳定的排序?其中一种情况是:原列表已经在某个字段上排好序,然而要排序的字段上可能有很多项是“相等”的。
比如有一个{name:string, age:number}[]数组,它【已经在name上按照字母顺序排好序】了,现在希望按照age来排序。假设有很多人的age是25,如果排序是稳定的话,就能保证这些25岁的人【在输出列表中是按照字母顺序排列的】,这样的话输出的列表会好看很多。
/** * @description 归并排序(稳定排序)。 * 此方法会改变原数组,如果不想破坏原数组,调用者自己创建数组副本作为参数。 */ function mergeSortJavaScript(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 (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); }
/** * @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(虽然说这道题不用排序效率更高)。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/94411.html
摘要:今天再来看看另外三种时间复杂度都是的排序算法,分别是希尔排序归并排序和快速排序。三数取中法求将放到数组的末尾总结这三种排序算法的平均时间复杂度都是,归并排序和快速排序的应用更广泛。 1. 回顾 前面说完了三种较为简单的排序算法,分别是冒泡排序,选择排序和插入排序,它们的平均情况时间复杂度都是 O(n2),比较的高,适合小规模的数据排序,其中插入排序的效率稍高,所以更推荐使用插入排序。今...
摘要:之所以把归并排序快速排序希尔排序堆排序放在一起比较,是因为它们的平均时间复杂度都为。归并排序是一种稳定的排序方法。因此,快速排序并不稳定。希尔排序思想先将整个待排序的记录序列分割成为若干子序列。 showImg(https://segmentfault.com/img/bVbvpYZ?w=900&h=250); 1. 前言 算法为王。 想学好前端,先练好内功,只有内功深厚者,前端之路才...
阅读 893·2023-04-25 18:51
阅读 1843·2021-09-09 11:39
阅读 3260·2019-08-30 15:53
阅读 2074·2019-08-30 13:03
阅读 1280·2019-08-29 16:17
阅读 546·2019-08-29 11:33
阅读 1837·2019-08-26 14:00
阅读 2097·2019-08-26 13:41