一、编码方式
- ASCII:规定了英语字符和二进制位之间的关系,用8个二进制表示,共规定了128个字符的编码。
- Unicode:ASCII只能表示英语,对于其他语言是不够用的,因此将所有符号进行编码,这就是Unicode。
- UTF-8:是Unicode的一种实现方式。Unicode和ASCII会有冲突,存储方式也多种多样,因此出现了UTF-8进行统一的编码方式,它使用
1~4个字节表示一个符号。 - UTF-16:字符用
2个字节或4个字节表示。 - UTF-32:字符用
4个字节表示。
字典序,顾名思义就是按照字典中出现的先后顺序进行比较。
1. 单个字符
对于单个数字和字符,字典序如下:
'0' < '1' < '2' < ... < '9' < 'a' < 'b' < ... < 'z'
2. 字符串
对于两个字符串,字典序的排序规则是按照从左到右的顺序进行比较,如果第1位相等,就比较第2位,直到有1位能比较出大小就停止比较。例如'ab' < 'ac'、'101' < '11'。
二、Array.prototype.sort()
在 js 中,sort()对数组的元素进行排序,默认会 「先将元素转换为字符串,然后按照各个字符的ASCII码进行排序,注意不是按照实际大小排序」,会改变原数组。
如果想让 sort 按照自定义方式排序,就需要传入一个比较函数作为参数。
// 语法
arr.sort([compareFunction])
比较函数compareFunction用来指定排列顺序,虽然它是可选的,但 强烈建议写上,规则如下:
(1)如果compareFunction(a, b) < 0,那么a排在b之前;
(2)如果compareFunction(a, b) > 0,那么b排在a之前;
(3)对于compareFunction(a, b) = 0这种情况,ECMAScript 标准并不会保证a和b的相对位置不变。自ES10(ECMAScript 2019)起,规范才要求Array.prototype.sort为 「稳定排序」。
// 常用的比较函数
a.nums((a, b) => a - b); // 升序,a-b > 0,b 排在 a 之前
b.nums((a, b) => b - a); // 降序
三、不同版本sort解读
1. 旧版源码(7.0版本前)
思路:数组长度小于10时,使用 「插入排序」,否则使用 「快速排序」。
-
InsertionSort:在数组长度小于10时执行插入排序算法
-
GetThirdIndex:对于快排来说,不同的基准元也会影响到排序时的比较次数,通过该方法获取较为合适的基准元作为快排的基准元。
-
quickSort:通过GetThirdIndex获得基准,从而实现快排。
2. v8源码
-
舍弃了快速排序,因为最坏情况下,时间复杂度会降到 O(n^2)。
-
采用一种混合排序的算法
TimSort。在数据量小的子数组中使用 「插入排序」,然后再使用 「归并排序」 将有序的子数组合并,时间复杂度为O(nlogn)。
因此sort()算法的实现取决于不同的JS引擎中具体的实现,无法保证排序的时间和空间复杂性。
扩展