鸣谢
本文参考文章或视频链接如下:
在文章开头对相关作者表示诚挚的感谢与敬意。
什么是排序
将杂乱无章的数据元素,通过一定的方法按关键字顺序排列的过程叫做排序。
排序分为内部排序和外部排序:
- 内部排序:若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序。
- 外部排序:外部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的。 待排序的记录存储在外存上,排序时把数据一部分一部分的调入内存进行排序,在排序中需要多次进行内外存的交互,对外存文件中的记录进行排序后的结果仍然被放到原有文件中。这种排序方法就称外部排序。
稳定排序: 假设在待排序的文件中,存在两个或两个以上的记录具有相同的关键字,在用某种排序法排序后,若这些相同关键字的元素的相对次序仍然不变,则这种排序方法是稳定的。
为什么需要排序?
系统熵决定了一个问题被解决的难易程度。 熵是一个用来衡量系统混乱程度的物理学概念。一个系统越混乱,熵越大,反之,一个系统越有序,熵越小。频繁查找的场景,一次排序,多次查找,将一个序列变成有序序列,可以很大程度降低问题的复杂性。
常见的排序算法大概有十种,下图罗列了它们的名字和时间复杂度等信息:
关于排序我们先从三个最基本的排序开始介绍。
冒泡排序
选择排序
插入排序
下面我们介绍的两种算法的核心思想是 “分治”。它的思想就是将一个大问题拆分为若干个小问题,针对这些小问题分别进行求解,再将小问题的解整合到大问题的解里。
从上面这句话的介绍可以看出,用 “分治” 思想解决问题大概分为下面三个步骤:
- 将大问题拆分为小问题
- 求解每个小问题的解
-
归并排序
使用归并排序对给出的数组: arr = [10, 2, 89, 43, 211, 455, 888] 进行从小到大的排序,
思路:
首先我们要从中间对数组进行分割,分割到每个数组中只有一个元素
- 然后对分割的数组进行两两合并,合并时候注意一定要有序合并
- 当所有分割的数组都被合并完后就得到了最终排序的数组 ```javascript console.log(mergeSort([ 10, 3, 5, 89, 23, 1, 90 ])); // [1, 3, 5, 10, 23, 89, 90]
function mergeSort(arr) { const len = arr.length; // 数组的长度小于等于1的时候没必要排序,直接返回即可 if (len <= 1) return arr;
// 获取分割点 const mid = Math.floor(len / 2); // 将数组从中间分为左右两个数组 const leftArr = mergeSort(arr.slice(0, mid)); const rightArr = mergeSort(arr.slice(mid));
// 对分割后的数据进行排序合并 return mergeArr(leftArr, rightArr); } /* 合并两个有序数组:
- 同时遍历两个数组,比较当前元素的大小,将小的推到结果数组中;
当某个数组遍历完后,看看有没有哪个数组还剩下元素,因为数组是升序的,剩余的元素肯定比结果数组中的元素大,所以直接将剩余元素合并到结果数组中 */ function mergeArr(arr1, arr2) { const len1 = arr1.length,
len2 = arr2.length, res = [];let i = 0,
j = 0;while (i < len1 && j < len2) {
if (arr1[i] < arr2[j]) { res.push(arr1[i]); i++; } else { res.push(arr2[j]); j++; }}
if (i < len1) {
return res.concat(arr1.slice(i));} return res.concat(arr2.slice(j)); }
