|
1 | 1 | ## 1. 选择排序算法思想
|
2 | 2 |
|
3 | | -> 选择排序(Selection Sort)基本思想: |
| 3 | +> **选择排序(Selection Sort)基本思想**: |
4 | 4 | >
|
5 | | -> 第 `i` 趟排序从序列的后 `n − i + 1 (i = 1, 2, ..., n − 1)` 个元素中选择一个值最小的元素与该 `n - i + 1` 个元素的最前面那个元素交换位置,即与整个序列的第 `i` 个位置上的元素交换位置。如此下去,直到 `i == n − 1`,排序结束。 |
| 5 | +> 将序列分为两部分:前边 `i - 1` 个元素为已排序部分,后边 `n - i + 1` 个元素为未排序部分。第 `i` 趟排序从未排序部分 `n − i + 1 (i = 1, 2, ..., n − 1)` 个元素中选择一个值最小的元素与未排序部分最前面那个元素交换位置,即与整个序列的第 `i` 个位置上的元素交换位置。如此下去,直到所有元素都变为已排序部分,排序结束。 |
6 | 6 |
|
7 | | -可以简述为:每一趟排序中,从剩余未排序元素中选择一个最小的元素,与未排好序的元素最前面的那个元素交换位置。 |
| 7 | +简单来说,「选择排序算法」是在每一趟排序中,从未排序部分中选出一个值最小的元素,与未排序部分第 `1` 个元素交换位置,从而将该元素划分到已排序部分。 |
8 | 8 |
|
9 | 9 | ## 2. 选择排序算法步骤
|
10 | 10 |
|
11 | | -- 在算法中设置整型变量 `i`,既可以作为排序趟数的计算,同时也作为执行第 `i` 趟排序时,参加排序的后 `n − i + 1` 个元素的第 `1` 个元素的位置。 |
12 | | -- 整型变量 `min_i` 记录这 `n − i + 1` 个元素中值最小元素的位置。 |
13 | | -- 每一趟排序开始,先另 `min_i = i` (即暂时假设序列的第 `i` 个元素为值最小者,以后经过比较后视实际情况再正式确定最小值元素的位置)。 |
14 | | -- 第 `i` 趟排序比较结束时,这 `n − i + 1` 个元素中真正的值最小元素为下标 `min_i` 对应的元素。此时,若有 `min_i == i`,说明值最小元素就是这 `n − i + 1` 个元素的第 `1` 个元素,意味着此趟排序不必进行元素交换。 |
| 11 | +1. 第 `1` 趟排序: |
| 12 | + 1. 无已排序部分,把第 `1` ~ `n `个元素(总共 `n ` 个元素)作为未排序部分。 |
| 13 | + 2. 遍历 `n` 个元素,使用变量 `min_i` 记录 `n` 个元素中值最小的元素位置。 |
| 14 | + 3. 将 `min_i` 与未排序部分第 `1` 个元素(也就是序列的第 `1` 个元素)交换位置。如果未排序部分第 `1` 个元素就是值最小的元素位置,则不用交换。 |
| 15 | + 4. 此时第 `1` 个元素为已排序部分,剩余第 `2` ~ `n` 个元素(总共 `n - 1` 个元素)为未排序部分。 |
| 16 | +2. 第 `2` 趟排序: |
| 17 | + 1. 遍历剩余 `n - 1` 个元素,使用变量 `min_i` 记录 `n - 1` 个元素中值最小的元素位置。 |
| 18 | + 2. 将 `min_i` 与未排序部分第 `1` 个元素(也就是序列的第 `2` 个元素)交换位置。如果未排序部分第 `1` 个元素就是值最小的元素位置,则不用交换。 |
| 19 | + 3. 此时第 `1` ~ `2` 个元素为已排序部分,剩余第 `3` ~ `n` 个元素(总共 `n - 2` 个元素)为未排序部分。 |
| 20 | +3. 依次类推,对剩余 `n - 2` 个元素重复上述排序过程,直到所有元素都变为已排序部分,则排序结束。 |
15 | 21 |
|
16 | 22 | ## 3. 选择排序动画演示
|
17 | 23 |
|
18 | | - |
| 24 | + |
| 25 | + |
| 26 | +1. 初始序列为:`[6, 2, 3, 5, 1, 4]`。 |
| 27 | +2. 第 `1` 趟排序,无已排序部分,把 `[6, 2, 3, 5, 1, 4]`(总共 `6 ` 个元素)作为未排序部分: |
| 28 | + 1. 遍历这 `6` 个元素,使用变量 `min_i` 记录 `6` 个元素中值最小(值为 `1`)的元素位置,也就是第 `5` 个元素位置。 |
| 29 | + 2. 将 `min_i` 与未排序部分第 `1` 个元素(也就是序列的第 `1` 个元素)交换位置,就是将元素 `6` 和元素 `1` 交换位置。 |
| 30 | + 3. 此时 `[1]` 为已排序部分,剩余 `[2, 3, 5, 6, 4]`(总共 `5` 个元素)为未排序部分。此时序列为 `[1, 2, 3, 5, 6, 4]`。 |
| 31 | +3. 第 `2` 趟排序,把 `[1]` 作为已排序部分,把剩余 `[2, 3, 5, 6, 4] `(总共 `5` 个元素)作为未排序部分。 |
| 32 | + 1. 遍历剩余 `5` 个元素,使用变量 `min_i` 记录 `5` 个元素中值最小的元素位置,也就是第 `2` 个元素位置。 |
| 33 | + 2. 因为值最小的元素位置 `min_i` 就是未排序部分第 `1` 个元素,所以不用交换。 |
| 34 | + 3. 此时 `[1, 2]` 为已排序部分,剩余 `[3, 5, 6, 4]`(总共 `4` 个元素)为未排序部分。 |
| 35 | +4. 依次类推,对剩余 `4` 个元素重复上述排序过程,直到所有元素都变为已排序部分,则排序结束。此时,序列变为 `[1, 2, 3, 4, 5, 6]`。 |
19 | 36 |
|
20 | 37 | ## 4. 选择排序算法分析
|
21 | 38 |
|
22 | | -对于具有 `n` 个元素的序列采用选择排序方法要经过 `n - 1` 趟排序。 |
| 39 | +- **时间复杂度**:排序法所进行的元素之间的比较次数与序列的原始状态无关,时间复杂度总是 $O(n^2)$。 |
| 40 | + - 这是因为无论序列中元素的初始排列状态如何,第 `i` 趟排序要找出值最小元素都需要进行 `n − i` 次元素之间的比较。因此,整个排序过程需要进行的元素之间的比较次数都相同,为 $∑^n_{i=2}(i - 1) = \frac{n(n−1)}{2}$ 次。 |
| 41 | +- **选择排序适用情况**:选择排序方法在排序过程中需要移动较多次数的元素,并且排序时间效率比较低。因此,选择排序方法比较适合于参加排序序列的数据量较小的情况。选择排序的主要优点是仅需要原地操作无需占用其他空间就可以完成排序,因此在空间复杂度要求较高时,可以考虑选择排序。 |
23 | 42 |
|
24 | | -- 当原始序列是一个按值递增序列(升序)时,元素的移动次数最少,为 `0` 次。当序列初始时是一个按值递减序列(逆序)时,元素的移动次数最多,为 3ドル(n − 1)$ 次(`3` 是交换 `arr[i]` 与 `arr[min_i]` 的执行次数)。 |
25 | | -- 但是,无论序列中元素的初始排列状态如何,第 `i` 趟排序要找出值最小元素都需要进行 `n − i` 次元素之间的比较。因此,整个排序过程需要进行的元素之间的比较次数都相同,为 $∑^n_{i=2}(i - 1) = \frac{n(n−1)}{2}$ 次。 |
26 | | -- 这说明选择排序法所进行的元素之间的比较次数与序列的原始状态无关,同时可以确定算法的时间复杂度为 $O(n^2)$。 |
27 | | -- 由于值最小元素与未排好序的元素中第 `1` 个元素的交换动作是在不相邻的元素之间进行的,因此很有可能会改变值相同元素的前后位置,因此,选择排序法是一种不稳定的排序方法。 |
| 43 | +- **排序稳定性**:由于值最小元素与未排序部分第 `1` 个元素的交换动作是在不相邻的元素之间进行的,因此很有可能会改变值相同元素的前后位置,因此,选择排序法是一种 **不稳定排序算法**。 |
28 | 44 |
|
29 | 45 | ## 5. 选择排序代码实现
|
30 | 46 |
|
31 | 47 | ```Python
|
32 | 48 | class Solution:
|
33 | 49 | def selectionSort(self, arr):
|
34 | 50 | for i in range(len(arr) - 1):
|
35 | | - # 记录未排序序列中最小数的索引 |
| 51 | + # 记录未排序部分中最小值的位置 |
36 | 52 | min_i = i
|
37 | 53 | for j in range(i + 1, len(arr)):
|
38 | 54 | if arr[j] < arr[min_i]:
|
39 | 55 | min_i = j
|
40 | | - # 如果找到最小数,将 i 位置上元素与最小数位置上元素进行交换 |
| 56 | + # 如果找到最小值的位置,将 i 位置上元素与最小值位置上的元素进行交换 |
41 | 57 | if i != min_i:
|
42 | 58 | arr[i], arr[min_i] = arr[min_i], arr[i]
|
43 | 59 | return arr
|
|
0 commit comments