1
- ### 常见基础排序算法
1
+ ### 2常见基础排序算法
2
2
3
3
4
4
5
5
#### 排序算法分类
6
6
7
- ![ 排序算法分类] ( https ://i.loli.net/2019/06/10/5cfe3bf15a32392750.png )
7
+ ![ 排序算法分类] ( http ://ww2.sinaimg.cn/large/006y8mN6ly1g68uopou69j30ko0dzwgb.jpg )
8
8
9
9
10
10
#### 时间复杂度
@@ -38,51 +38,73 @@ O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(2^n) < O(n^3) < O(n^n)
38
38
39
39
``` java
40
40
public void bubbleSort(int [] array) {
41
- int temp;
42
- // 外层移动基准元素索引
43
- for (int i = 0 ; i < array. length - 1 ; i++ ) {
44
- // 内层对基准元素与之后的每个做比较,冒泡排序
45
- for (int j = i + 1 ; j < array. length; j++ ) {
46
- // 大的值,向上冒泡
47
- if ((temp = array[i]) > array[j]) {
48
- array[i] = array[j];
49
- array[j] = temp;
50
- }
51
- }
52
- }
41
+ if (array == null ) {
42
+ return ;
43
+ }
44
+
45
+ int temp;
46
+ // 冒泡次数
47
+ for (int i = array. length - 1 ; i > 0 ; i-- ) {
48
+ // 冒泡排序
49
+ for (int j = 0 ; j < i; j++ ) {
50
+ // 将大值交换到后面
51
+ if (array[j] > array[j + 1 ]) {
52
+ temp = array[j];
53
+ array[j] = array[j + 1 ];
54
+ array[j + 1 ] = temp;
55
+ }
56
+ }
57
+ }
53
58
}
54
59
```
55
60
56
61
57
62
58
63
##### 2. 快速排序 ★★★★★
59
64
65
+ 基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
66
+
60
67
``` java
61
68
public void quickSort(int [] array, int left, int right) {
69
+ if (array == null ) {
70
+ return ;
71
+ }
72
+
62
73
if (left < right) {
63
74
int i = left;
64
75
int j = right;
65
- int temp = array[i];
76
+ int temp = array[i]; // 选取一端值为基准值
66
77
67
78
while (i < j) {
79
+ // 如果 j 处值大于等于基准值,那么不用交换数据,直接将 j 向前移动,
80
+ // 直到 i 等于 j 或者 j 处值比基准值小
68
81
while (i < j && array[j] >= temp) {
69
82
j-- ;
70
83
}
84
+ // 如果 i < j,说明 j 处值比基准值小(根据上面循环判断)
71
85
if (i < j) {
86
+ // 交换 j 与 i 处的值,并将 i 向后移动
72
87
array[i++ ] = array[j];
73
88
}
74
89
90
+
91
+ // 如果 i 处值小于等于基准值,那么将i向后移动就可以了
75
92
while (i < j && array[i] <= temp) {
76
93
i++ ;
77
94
}
95
+ // 如果 i < j,说明 i 处值比基准值大(根据上面循环判断)
78
96
if (i < j) {
97
+ // 交换 i 与 j 处的值,并将 i 向前移动
79
98
array[j-- ] = array[i];
80
99
}
81
100
101
+ // 最后将临时基准值填充到 i 处
82
102
array[i] = temp;
83
- quickSort(array, left, i - 1 );
84
- quickSort(array, i + 1 , right);
103
+ // 对两段各自快速排序
85
104
}
105
+
106
+ quickSort(array, left, i - 1 );
107
+ quickSort(array, i + 1 , right);
86
108
}
87
109
}
88
110
```
@@ -93,12 +115,18 @@ public void quickSort(int[] array, int left, int right) {
93
115
94
116
``` java
95
117
public void insertionSort(int [] array) {
118
+ if (array == null ) {
119
+ return ;
120
+ }
121
+ // 和冒泡排序有些类似,这里是遍历趟数
96
122
for (int i = 0 ; i < array. length; i++ ) {
97
- int temp = array[i];
123
+ // 精髓是从局部有序,到整体有序
124
+ int temp = array[i]; // 当前基准元素
98
125
int j;
99
126
for (j = i; j > 0 && array[j - 1 ] > temp; j-- ) {
100
- array[j] = array[j - 1 ];
127
+ array[j] = array[j - 1 ]; // 下一个元素比基准元素大,下一个元素向后移动
101
128
}
129
+ // 最后比较当前元素和基准元素大小
102
130
if (array[j] > temp) {
103
131
array[j] = temp;
104
132
}
@@ -108,19 +136,22 @@ public void insertionSort(int[] array) {
108
136
109
137
110
138
111
- ##### 4. 希尔排序 ★★★☆☆
139
+ ##### 4. 希尔排序(缩写增量-直接插入排序) ★★★☆☆
112
140
113
141
``` java
114
142
public void shellSort(int [] array) {
115
- // 增量
143
+ if (array == null ) {
144
+ return ;
145
+ }
146
+ // 计算增量
116
147
for (int d = array. length / 2 ; d > 0 ; d /= 2 ) {
117
148
// 分组
118
- for (int x = 0 ; x < d; x ++ ) {
119
- // 直接插入排序 (第 x 组的第2个元素起步 )
120
- for (int i = x + d; i < array. length; i += d) {
149
+ for (int g = 0 ; g < d; g ++ ) {
150
+ // 插入排序 (第 x 组的第 d 个增量元素起步)(直接插入排序的增量是 1,这里是 d,需注意下 )
151
+ for (int i = g + d; i < array. length; i += d) {
121
152
int temp = array[i];
122
- int j = i ;
123
- for (; j > d && array[j - d] > temp; j -= d) {
153
+ int j;
154
+ for (j = i ; j > d && array[j - d] > temp; j -= d) {
124
155
array[j] = array[j - d];
125
156
}
126
157
if (array[j] > temp) {
@@ -138,19 +169,26 @@ public void shellSort(int[] array) {
138
169
139
170
``` java
140
171
public void selectionSort(int [] array) {
141
- int minIndex;
172
+ if (array == null ) {
173
+ return ;
174
+ }
175
+
176
+ int index;
142
177
int temp;
143
- for (int i = 0 ; i < array. length - 1 ; i++ ) {
144
- minIndex = i;
145
- for (int j = i + 1 ; j < array. length; j ++ ) {
146
- if (array[minIndex] > array[j]) {
147
- minIndex = j;
178
+ // 做出的选择次数
179
+ for (int i = array. length - 1 ; i > 0 ; i-- ) {
180
+ index = 0 ;
181
+ for (int j = 1 ; j < i; j++ ) {
182
+ // 选择一个最大的值(记录索引)
183
+ if (array[j] > array[index]) {
184
+ index = j;
148
185
}
149
186
}
150
- if (minIndex > i) {
151
- temp = array[i];
152
- array[i] = array[minIndex];
153
- array[minIndex] = temp;
187
+ // 将选出的最大值换到一端
188
+ if (array[index] > array[i]) {
189
+ temp = array[index];
190
+ array[index] = array[i];
191
+ array[i] = temp;
154
192
}
155
193
}
156
194
}
@@ -162,31 +200,43 @@ public void selectionSort(int[] array) {
162
200
163
201
``` java
164
202
public void heapSort(int [] array) {
203
+ if (array == null ) {
204
+ return ;
205
+ }
206
+
165
207
for (int i = array. length / 2 - 1 ; i >= 0 ; i-- ) {
208
+ // 先调整堆(选择一个最大值放到堆顶)
166
209
adjustHeap(array, i, array. length);
167
210
}
168
211
169
212
for (int i = array. length - 1 ; i > 0 ; i-- ) {
213
+ // 将堆顶的元素与其他元素比较并交换
170
214
swap(array, 0 , i);
215
+ // 再调整堆
171
216
adjustHeap(array, 0 , i);
172
217
}
173
218
}
174
219
175
- private void adjustHeap(int [] array, int i, int length) {
176
- int temp = array[i];
220
+ // 调整堆,使得堆顶元素值大于等于其子节点值
221
+ private void adjustHeap(int [] array, int top, int length) {
222
+ int temp = array[top];
177
223
178
- for (int j = i * 2 + 1 ; j < length; j = j * 2 + 1 ) {
179
- if (j + 1 < length && array[j + 1 ] > array[j]) {
180
- j++ ;
224
+ for (int i = top * 2 + 1 ; i < length; i = i * 2 + 1 ) {
225
+ // (如果存在的化)从左右子节点找出值最大的子节点
226
+ if (i + 1 < length && array[i + 1 ] > array[i]) {
227
+ i++ ;
181
228
}
182
- if (array[j ] > temp) {
183
- array[i ] = array[j ];
184
- i = j ;
229
+ if (array[i ] > temp) {
230
+ array[top ] = array[i ];
231
+ top = i ;
185
232
} else {
186
233
break ;
187
234
}
188
235
}
189
- array[i] = temp;
236
+
237
+ if (array[top] > temp) {
238
+ array[top] = temp;
239
+ }
190
240
}
191
241
192
242
private void swap(int [] array, int a, int b) {
@@ -202,24 +252,30 @@ private void swap(int[] array, int a, int b) {
202
252
203
253
``` java
204
254
public void mergeSort(int [] array) {
255
+ if (array == null ) {
256
+ return ;
257
+ }
258
+
205
259
int [] aux = new int [array. length];
206
260
sort(array, 0 , array. length - 1 , aux);
207
261
}
208
262
209
263
private void sort(int [] array, int left, int right,int [] aux) {
210
264
if (left < right) {
211
265
int mid = (left + right) / 2 ;
266
+ // 先分后合
212
267
sort(array, left , mid, aux);
213
268
sort(array, mid + 1 , right, aux);
214
269
merge(array, left, mid, right, aux);
215
270
}
216
271
}
217
272
218
273
private void merge(int [] array, int left, int mid, int right, int [] aux){
274
+ int t = 0 ;
219
275
int l = left;
220
276
int m = mid + 1 ;
221
- int t = 0 ;
222
277
278
+ // 判断元素值大小,按大小排序到辅助数组上
223
279
while (l <= mid && m <= right) {
224
280
if (array[l] <= array[m]) {
225
281
aux[t++ ] = array[l++ ];
@@ -228,14 +284,15 @@ private void merge(int[] array, int left, int mid, int right, int[] aux){
228
284
}
229
285
}
230
286
231
- // 填充剩余元素
287
+ // 把剩余元素填充到辅助数组上
232
288
while (l <= mid) {
233
289
aux[t++ ] = array[l++ ];
234
290
}
235
291
while (m <= right) {
236
292
aux[t++ ] = array[m++ ];
237
293
}
238
294
295
+ // 将辅助线数组上的元素复制到需要排序的数组上
239
296
t = 0 ;
240
297
while (left <= right) {
241
298
array[left++ ] = aux[t++ ];
0 commit comments