选择排序

从待排序的数据元素中选出最小(或最大)的一个元素,存放在与序列的第一个元素交换位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完

  • 时间复杂度

    最好:O(n2)

    最坏:O(n2)

    平均:O(n2)

  • 空间复杂度 —— O(1)

  • 稳定性:不稳定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function selectSort(arr) {
let len = arr.length;
for (let i = 0; i < len; i++) {
let temp = arr[i], minIndex = i;
for (j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
return arr;
}

其排序过程为

1
2
3
4
5
6
7
8
selectSort([4, 9, 1, 7, 3, 5]);

0: 1 9 4 7 3 5
1: 1 3 4 7 9 5
2: 1 3 4 7 9 5
3: 1 3 4 5 9 7
4: 1 3 4 5 7 9
5: 1 3 4 5 7 9

特点:

  1. 运行时间与输入无关

  2. 数据移动次数是最少的,共 n 此交换

插入排序

将每一个元素插入到已经排好序的序列中

  • 时间复杂度

    最好:O(n)

    最坏:O(n2)

    平均:O(n2)

  • 空间复杂度 —— O(1)

  • 稳定性:稳定

1
2
3
4
5
6
7
8
9
function insertSort(arr) {
let len = arr.length;
for (let i = 1; i < len; i++) {
for (j = i; j > 0 && arr[j] < arr[j - 1]; j--) {
[arr[j], arr[j - 1]] = [arr[j - 1], arr[j]];
}
}
return arr;
}

其排序过程为

1
2
3
4
5
6
7
insertSort([4, 9, 1, 7, 3, 5])

1: 4 9 1 7 3 5
2: 1 4 9 7 3 5
3: 1 4 7 9 3 5
4: 1 3 4 7 9 5
5: 1 3 4 5 7 9

另一种写法,在内循环中将较大的元素向右移动而不交换

1
2
3
4
5
6
7
8
9
10
11
function insertSort(arr) {
let len = arr.length;
for (let i = 1; i < len; i++) {
let temp = arr[i];
for (j = i - 1; j >= 0 && temp < arr[j]; j--) {
arr[j + 1] = arr[j];
}
arr[j + 1] = temp;
}
return arr;
}

特点:插入排序所需的时间取决于输入元素的初始顺序

冒泡排序

遍历若干次要排序的序列,每次遍历时,从前往后依次的比较相邻两个数的大小;如果前者比后者大,则交换它们的位置。这样,每一次遍历之后,最大的元素就在序列的末尾。重复此操作,直到整个序列都有序为止

  • 时间复杂度

    最好:O(n)

    最坏:O(n2)

    平均:O(n2)

  • 空间复杂度 —— O(1)

  • 稳定性:稳定

1
2
3
4
5
6
7
8
9
10
11
12
function bubbleSort(arr) {
let len = arr.length;
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
console.log(`${i}: ${arr}`)
}
return arr;
}

其排序过程为

1
2
3
4
5
6
7
8
bubbleSort([4, 9, 1, 7, 3, 5])

0: 4 1 7 3 5 9
1: 1 4 3 5 7 9
2: 1 3 4 5 7 9
3: 1 3 4 5 7 9
4: 1 3 4 5 7 9
5: 1 3 4 5 7 9

一种优化的方法:

添加一个标记,如果一趟遍历中发生了交换,则标记为true,否则为false。如果某一趟没有发生交换,说明排序已经完成,可以直接返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function bubbleSort(arr) {
let len = arr.length;
for (let i = 0; i < len; i++) {
let needSwap = false;
for (let j = 0; j < len - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
needSwap = true;
}
}
if (!needSwap) return arr;
}
return arr;
}
1
2
3
4
5
6
bubbleSort([4, 9, 1, 7, 3, 5])

0: 4 1 7 3 5 9 (true)
1: 1 4 3 5 7 9 (true)
2: 1 3 4 5 7 9 (true)
3: 1 3 4 5 7 9 (false)

希尔排序

希尔排序是把元素按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的元素越来越多,当增量减至1时,整个序列恰被分成一组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function shellSort(arr) {
let len = arr.length, gap = 1;
while (gap < len / 3) {
gap = gap * 3 + 1;
}
while (gap >= 1) {
for (let i = gap; i < len; i++) {
for (let j = i; j >= gap && arr[j] < arr[j - gap]; j -= gap) {
[arr[j], arr[j - gap]] = [arr[j - gap], arr[j]];
}
console.log(`${gap}: ${arr}`)
}
gap = Math.floor(gap / 3);
}
return arr;
}

其排序过程为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
shellSort([4, 9, 1, 7, 3, 5, 52, 10, 98, 8, 24, 30, 2, 79, 43])

gap = 13 4 9 1 7 3 5 52 10 98 8 24 30 2 79 43
4 9 1 7 3 5 52 10 98 8 24 30 2 79 43
gap = 4 3 9 1 7 4 5 52 10 98 8 24 30 2 79 43
3 5 1 7 4 9 52 10 98 8 24 30 2 79 43
3 5 1 7 4 9 52 10 98 8 24 30 2 79 43
3 5 1 7 4 9 52 10 98 8 24 30 2 79 43
3 5 1 7 4 9 52 10 98 8 24 30 2 79 43
3 5 1 7 4 8 52 10 98 9 24 30 2 79 43
3 5 1 7 4 8 24 10 98 9 52 30 2 79 43
3 5 1 7 4 8 24 10 98 9 52 30 2 79 43
2 5 1 7 3 8 24 10 4 9 52 30 98 79 43
2 5 1 7 3 8 24 10 4 9 52 30 98 79 43
2 5 1 7 3 8 24 10 4 9 43 30 98 79 52
gap = 1 2 5 1 7 3 8 24 10 4 9 43 30 98 79 52
1 2 5 7 3 8 24 10 4 9 43 30 98 79 52
1 2 5 7 3 8 24 10 4 9 43 30 98 79 52
1 2 3 5 7 8 24 10 4 9 43 30 98 79 52
1 2 3 5 7 8 24 10 4 9 43 30 98 79 52
1 2 3 5 7 8 24 10 4 9 43 30 98 79 52
1 2 3 5 7 8 10 24 4 9 43 30 98 79 52
1 2 3 4 5 7 8 10 24 9 43 30 98 79 52
1 2 3 4 5 7 8 9 10 24 43 30 98 79 52
1 2 3 4 5 7 8 9 10 24 43 30 98 79 52
1 2 3 4 5 7 8 9 10 24 30 43 98 79 52
1 2 3 4 5 7 8 9 10 24 30 43 98 79 52
1 2 3 4 5 7 8 9 10 24 30 43 79 98 52
1 2 3 4 5 7 8 9 10 24 30 43 52 79 98

归并排序