Skip to content

Commit 109a9e0

Browse files
committed
[A] 添加冒泡、选择、插入、快速排序文章
1 parent a6f6c3c commit 109a9e0

8 files changed

Lines changed: 390 additions & 8 deletions

File tree

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,34 @@
1414
- [基数排序]()(待续)
1515
- [堆排序](https://github.com/coderbruis/AlgorithmsInJava/blob/master/notes/algorithms/%E5%A0%86%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95.md) 【更新中】
1616

17+
## 排序算法总结
18+
19+
| 排序名 | 平均时间复杂度 | 空间复杂度 | 优势 | 劣势 | 适用场景 | 稳定性 |
20+
| :--: | :------: | :----------: | :--: | :--: | :-----------------------: | :--: |
21+
| 冒泡排序 | O(n^2) | O(1) | | | | 稳定 |
22+
| 插入排序 | O(n^2) | O(1) | | | | 稳定 |
23+
| 计数排序 | | O(M) | | | 对于用例少的数据,比如对人的年龄排序或者身高排序。 | 稳定 |
24+
| 基数排序 | O(d(n+r)) | O(M) | | | | 稳定 |
25+
| 桶排序 | | | | | | 稳定 |
26+
| 选择排序 | O(n^2) | O(1) | | | | 不稳定 |
27+
| 归并排序 | O(nlogn) | O(N) | | | | 稳定 |
28+
| 快速排序 | O(nlogn) | O(logn)~O(n) | | | | 不稳定 |
29+
| 希尔排序 | O(nlogn) | O(1) | | | | 不稳定 |
30+
| 堆排序 | O(nlogn) | O(1) | | | | 不稳定 |
31+
32+
注意这里总结的都是平均时间复杂度,例如插入排序,如果是有序的数组,则时间复杂度会退化成O(n)。而快速排序,对于每次选择的p位置都是末尾位置,则会退化成时间复杂度为O(n^2)(通过让p的位置随机来解决这个问题)。
33+
对于归并排序、快速排序、堆排序这三个O(nlogn)的排序来说,时间复杂度是有常数级别的区别的,但是快速排序是相对更快的一种排序。
34+
35+
这里还需要注意的是,对于插入排序、快速排序、堆排序来说,都是原地排序的,即不需要额外的空间;而归并排序则是非原地排序,需要借助额外空间。
36+
37+
> 排序算法的稳定性:对于相等的元素,在排序后,原来靠前的元素依然靠前,相等元素的相对位置没有发生改变。
38+
39+
> 除非面试题特别说明,否则认为要排序的数据范围是均匀分布的。
40+
41+
> 快速排序之所以叫快速排序,并不代表它比堆排序和归并排序优良。在最好情况下,它的渐进复杂度与 堆排序和归并排序是相同的。知识快速排序的常量系数比较小而已。
42+
43+
> 类库上提供的排序,并不是某一种算法的实现,而是综合了多种排序的综合排序。当数组比较小时,使用插入排序;当数组较大时,选择快速排序或其他的O(nlogn)的排序。
44+
1745
# 经典算法
1846

1947
- [KMP算法]()(待续)
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
## 前言
2+
3+
思路:每一趟遍历将最大元素冒泡到数组最后的位置;
4+
5+
动态图
6+
7+
![冒泡排序动态图](https://github.com/coderbruis/AlgorithmsInJava/blob/master/notes/pictures/bubbleSort.gif)
8+
9+
- 时间复杂度:O(N^2)
10+
- 空间复杂度:O(1)
11+
- 稳定性:稳定
12+
13+
## 正文
14+
15+
### 1. 实现代码
16+
17+
```
18+
public class BubbleSort {
19+
20+
// 方式;
21+
public static void sort(int[] arr) {
22+
int n = arr.length;
23+
boolean swapped = false;
24+
25+
do {
26+
swapped = false;
27+
for (int i = 1; i < n; i++) {
28+
if (arr[i - 1] > arr[i]) {
29+
swap(arr, i - 1, i);
30+
swapped = true;
31+
}
32+
}
33+
} while(swapped);
34+
}
35+
36+
// 方式2
37+
public static void sort2(int[] arr) {
38+
int n = arr.length;
39+
40+
if (n <= 1) {
41+
return;
42+
}
43+
44+
// 使用newn来进行优化
45+
int newn;
46+
47+
do {
48+
newn = 0;
49+
for (int i = 1; i < n; i++) {
50+
if (arr[i - 1] > arr[i]) {
51+
swap(arr, i - 1, i);
52+
// 记录当前排序最后一次交换的位置,在此之后的元素在下一轮扫描中均不考虑
53+
newn = i;
54+
}
55+
}
56+
n = newn;
57+
} while (newn > 0);
58+
59+
}
60+
61+
// 方式3
62+
public static void sort3(int[] arr) {
63+
int n = arr.length;
64+
if (n <= 1) {
65+
return;
66+
}
67+
68+
for (int i = 0; i < n; i++) {
69+
boolean flag = false;
70+
71+
// n - i - 1 表示每轮排序都会有一个最大元素冒泡到最大位置,因而每轮排序都会少一个遍历的元素
72+
for (int j = 0; j < n - i - 1; j++) {
73+
if (arr[j] < arr[j + 1]) {
74+
swap(arr, j, j + 1);
75+
flag = true;
76+
}
77+
}
78+
// 此轮排序没有数据交换,则退出排序
79+
if (!flag) {
80+
break;
81+
}
82+
}
83+
}
84+
85+
public static void swap(int[] arr, int i, int j) {
86+
int tmp = arr[i];
87+
arr[i] = arr[j];
88+
arr[j] = tmp;
89+
}
90+
}
91+
```
92+
93+
> 分析:对于方式一,由于每一趟排序都会将最大元素冒泡到最后一位,所以下一次排序就不用考虑最后一个位置的元素了,从而加速下一次排序的速度。代码中的方式2和方式3都是同样的优化思路。
94+
95+
## 参考
96+
97+
- [动态图参考](https://www.runoob.com/w3cnote/bubble-sort.html)

notes/algorithms/堆排序算法.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,20 @@
66

77
学完堆这种数据结构后,再来学堆排序,会简单的多。
88

9+
- 时间复杂度:O(NlogN)
10+
- 空间复杂度:O(1)
11+
- 稳定性:不稳定
12+
913
## 正文
1014

1115
### 1. 借助辅助空间
1216

1317

1418

15-
### 2. 原地堆排序
19+
### 2. 原地堆排序
20+
21+
22+
23+
## 参考
24+
25+
- [动态图参考](https://www.runoob.com/w3cnote/bubble-sort.html)

notes/algorithms/归并排序算法.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
![归并过程动态图](https://github.com/coderbruis/AlgorithmsInJava/blob/master/notes/pictures/mergeSort.gif)
1414
![分治思想](https://github.com/coderbruis/AlgorithmsInJava/blob/master/notes/pictures/1557906108-5066-20161218163120151-452283750.png)
1515

16+
- 时间复杂度:O(NlogN)
17+
- 空间复杂度:O(N)
18+
- 稳定性:不稳定
19+
1620
## 正文
1721

1822
### 1.(自顶向下)归并排序算法
@@ -28,4 +32,10 @@
2832
除此之外,自底向上排序的算法不需要额外的空间,空间复杂度为O(1)。自底向上有一个非常重要的作用,它可以通过O(NlogN)的
2933
时间复杂度去对链表这种数据结构进行排序。
3034

31-
**对链表进行O(NlogN)级别的排序**
35+
**对链表进行O(NlogN)级别的排序**
36+
37+
38+
39+
## 参考
40+
41+
- [动态图参考](https://www.runoob.com/w3cnote/bubble-sort.html)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
## 前言
2+
3+
4+
- 时间复杂度:O(NlogN)
5+
- 空间复杂度:O(N)
6+
- 稳定性:稳定
7+
8+
## 正文
9+
10+
### 1. 代码实现
11+
12+
```
13+
private int partition2(int[] nums, int lt, int gt) {
14+
int p = nums[n];
15+
int j = lt;
16+
for(int i = lt; i <= gt; i++) {
17+
if(nums[i] < p) {
18+
swap(nums, ++j, i);
19+
}
20+
}
21+
swap(nums, lt, j);
22+
return j;
23+
}
24+
25+
private int partition(int[] nums, int n, int m) {
26+
int p = nums[n];
27+
int j = n;
28+
int k = m + 1;
29+
int i = n + 1;
30+
while(i < k) {
31+
if(nums[i] < p) {
32+
swap(nums, ++j, i++);
33+
} else if(nums[i] > p) {
34+
swap(nums, --k, i);
35+
} else {// nums[i] == p
36+
i++;
37+
}
38+
}
39+
swap(nums, n, j);
40+
return j;
41+
}
42+
private void swap(int[] nums, int n, int m) {
43+
int tmp = nums[n];
44+
nums[n] = nums[m];
45+
nums[m] = tmp;
46+
}
47+
private void sort(int[] nums, int n, int m) {
48+
if(n > m) {
49+
return;
50+
}
51+
int p = partition(nums, n, m);
52+
sort(nums, n, p - 1);
53+
sort(nums, p + 1, m);
54+
}
55+
public void sort(int[] nums) {
56+
sort(nums, 0, nums.length);
57+
}
58+
59+
```
60+
61+
## 参考
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
## 前言
2+
3+
思路:插入排序就跟玩扑克牌一样,先把一部分牌给排好顺序,然后依次往后排剩下的牌,最终达到将所有牌都排序的效果。
4+
5+
动态图
6+
7+
![插入排序动态图](https://github.com/coderbruis/AlgorithmsInJava/blob/master/notes/pictures/insertionSort.gif)
8+
9+
- 时间复杂度:O(N^2)
10+
- 空间复杂度:O(1)
11+
- 稳定性:稳定
12+
13+
## 正文
14+
15+
### 1. 代码实现
16+
17+
```
18+
public class InsertionSort {
19+
// 方式1
20+
public static void sort(int[] arr) {
21+
int n = arr.length;
22+
for (int i = 0; i < n; i++) {
23+
for (int j = i; j > 0; j--) {
24+
// 注意这里j-1没有越界,因为j > 0进行了判断
25+
if (arr[j] < arr[j-1]) {
26+
swap(arr, j, j-1);
27+
} else {
28+
break;
29+
}
30+
}
31+
}
32+
}
33+
34+
// 方式2
35+
public static void sort2(int[] arr) {
36+
int n = arr.length;
37+
for (int i = 0; i < n; i++) {
38+
for (int j = i; j > 0 && arr[j] < arr[j-1]; j--) {
39+
// 注意这里j-1没有越界,因为j > 0进行了判断
40+
swap(arr, j, j-1);
41+
}
42+
}
43+
}
44+
45+
// 方式3,优化版
46+
public static void sort3(int[] arr) {
47+
int n = arr.length;
48+
for (int i = 0; i < n; i++) {
49+
// 获取需要比较的元素
50+
int e = arr[i];
51+
int j = i;
52+
for (; j > 0 && e < arr[j-1] ; j--) {
53+
// 如果满足条件,则前一位元素复制给后一位元素
54+
arr[j] = arr[j-1];
55+
}
56+
// 跳出循环,则将需要比较的e元素替换到j位置,j位置即最终停留的位置
57+
arr[j] = e;
58+
}
59+
}
60+
61+
public static void swap(int[] arr, int i, int j) {
62+
int tmp = arr[i];
63+
arr[i] = arr[j];
64+
arr[j] = tmp;
65+
}
66+
67+
public static void main(String[] args) {
68+
int [] arr = {6,2,1,5,4,3};
69+
sort2(arr);
70+
for (int n : arr) {
71+
System.out.println(n);
72+
}
73+
}
74+
}
75+
```
76+
77+
## 参考
78+
79+
- [动态图参考](https://www.runoob.com/w3cnote/bubble-sort.html)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
## 前言
2+
3+
思路:依次寻找[i, n)区间里的最小值的索引。
4+
5+
动态图
6+
7+
![选择排序动态图](https://github.com/coderbruis/AlgorithmsInJava/blob/master/notes/pictures/selectionSort.gif)
8+
9+
- 时间复杂度:O(N^2)
10+
- 空间复杂度:O(1)
11+
- 稳定性:不稳定
12+
13+
## 正文
14+
15+
### 1. 代码实现
16+
17+
```
18+
public class SelectionSort {
19+
20+
public static void sort(int[] arr) {
21+
22+
int n = arr.length;
23+
24+
for (int i = 0; i < n; i++) {
25+
int min = i;
26+
for (int j = i+1; i < n; i++) {
27+
if (arr[j] < arr[min]) {
28+
min = j;
29+
}
30+
}
31+
swap(arr, i, min);
32+
}
33+
}
34+
35+
public static void swap(int[] arr, int i, int j) {
36+
int tmp = arr[i];
37+
arr[i] = arr[j];
38+
arr[j] = tmp;
39+
}
40+
}
41+
```
42+
43+
## 参考
44+
45+
- [动态图参考](https://www.runoob.com/w3cnote/bubble-sort.html)

0 commit comments

Comments
 (0)