avatar

排序算法

排序算法

算法分类

1
2
比较类排序: 通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),也被称为非线性时间比较类排序
非比较类排序: 不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,也被称为线性时间非比较类排序
排序算法 比较类排序 交换排序 冒泡排序
快速排序
插入排序 简单插入排序
希尔排序
选择排序 简单选择排序
堆排序
归并排序 二路归并排序
多路归并排序
非比较排序 计数排序
桶排序
基数排序

算法复杂度

排序方法 时间复杂度(平均) 时间复杂度(最坏) 时间复杂度(最好) 空间复杂度 稳定性
插入排序 O(n²) O(n²) O(n) O(1) 稳定
希尔排序 O(n¹•³) O(n²) O(n) O(1) 不稳定
选择排序 O(n²) O(n²) O(n²) O(1) 不稳定
堆排序 O(nlog₂n) O(nlog₂n) O(nlog₂n) O(1) 不稳定
冒泡排序 O(n²) O(n²) O(n) O(1) 稳定
快速排序 O(nlog₂n) O(n²) O(nlog₂n) O(nlog₂n) 不稳定
归并排序 O(nlog₂n) O(nlog₂n) O(nlog₂n) O(n) 稳定
计数排序 O(n+k) O(n+k) O(n+k) O(n+k) 稳定
桶排序 O(n+k) O(n²) O(n) O(n+k) 稳定
基数排序 O(n*k) O(n*k) O(n*k) O(n+k) 稳定
## **相关概念**
1
2
3
4
稳定: 若a原本在b前面,而a=b,排序后a仍在b前面
不稳定: 若a原本在b前面,而a=b,排序后a可能出现在b后面
时间复杂度: 对排序数据的总的操作次数
空间复杂度: 指算法在计算机内执行时所需存储空间的度量,也是数据规模的函数

冒泡排序

依次比较相邻的两个元素,左边的元素若比右边的大,就将它俩的位置相互调换

动画演示

冒泡排序

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static List<Integer> bubbleSort(Integer... i) {

/* 临时变量 */
int snap;

/* 冒泡次数,排除排序可能出现的错误 */
for (int j = 0; j < i.length; j++) {
/* 冒泡排序 */
for (int l = 0; l < i.length - 1; l++) {
/* 与后一个数字比较大小,若这个数字大于下一个数字则将二者的顺序进行调换 */
if (i[l] > i[l + 1]) {
snap = i[l];
i[l] = i[l + 1];
i[l + 1] = snap;
}
}
}

return Arrays.asList(i);

}

选择排序

依次将从待排序的数组中选出最小的元素,将其放置到待排序的数组中的最左边

动画演示

选择排序

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static List<Integer> selectSort(Integer... i) {

int snap,
t /* 临时变量 */;

for (int j = 0; j < i.length; j++) {

/* 记录数组中最小值的下标 */
snap = j;

for (int l = snap + 1; l < i.length; l++)
/* 判断当前最小值是否大于后续值,若大于就将最小值的索引赋值给临时变量 */
if (i[snap] > i[l]) snap = l;

t = i[j];
i[j] = i[snap];
i[snap] = t;

}

return Arrays.asList(i);

}

快速排序

通过定位基准元素将待排序数组分成两部分,比关键字小和比关键字大的,再将这两部分通过递归达到有序排序的效果

动画演示

快速排序

代码实现

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public static List<Integer> quickSort(Integer[] i) {

quickSort(i, 0, i.length - 1);

return Arrays.asList(i);

}

private static void quickSort(Integer[] i, Integer start, Integer end) {

/* 当条件不满足时,跳出程序,避免堆栈溢出 */
if (start > end) return;

/* 变量定义 */
int datum = i[start],
j = start,
l = end,
temporary;

while (j < l) {

/* 获取比基准元素小的元素在数组中的索引 */
while (datum <= i[l] && j < l) l--;

/* 获取比基准元素大的元素在数组中的索引 */
while (datum >= i[j] && j < l) j++;

if (j < l) {
temporary = i[l];
i[l] = i[j];
i[j] = temporary;
}
}

/* 将基准元素与j、k相等的索引处的数字交换 */
i[start] = i[j];
i[j] = datum;

/* 递归调用当前基准元素左边的数组 */
quickSort(i, start, j - 1);
/* 递归调用当前基准元素右边的数组 */
quickSort(i, j + 1, end);

}

插入排序

从数组的索引1开始,将数组中待排序的元素按照升序规则插入到已排序好的数组中

动画实现

插入排序

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static List<Integer> insertionSort(Integer... i) {

/* 临时变量 */
int temporary;

/* 从索引1处循环整个数组 */
for (int j = 1; j < i.length; j++) {
/* 倒序循环已排序的数组 */
for (int l = j; l > 0; l--) {
/* 与已排序的数组元素进行对比,当前元素小于上一个元素,就与其进行位置调换 */
if (i[l] < i[l - 1]) {
temporary = i[l];
i[l] = i[l - 1];
i[l - 1] = temporary;
}
}
}

return Arrays.asList(i);

}

以下仅为动画演示,暂未进行研究

计数排序

动画演示

计数排序

代码实现

1
在这里插入代码片

基数排序

动画演示

基数排序

代码实现

1
在这里插入代码片

归并排序

动画演示

归并排序

代码实现

1
在这里插入代码片

堆排序

动画演示

堆排序

代码实现

1
在这里插入代码片
文章作者: 123
文章链接: https://gao5805123.github.io/123/2021/02/26/%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 123
打赏
  • 微信
    微信
  • 支付宝
    支付宝