排序算法-直接选择排序

通过直接选择排序可以初步明白时间复杂度和空间复杂度的概念,以及直接选择排序的思路

实现过程

现将一步一步的展现一个无序集合[2,1,5,3,7]进行直接选择排序(本文升序)的过程.首先将该集合分为2个部分,第一个部分为有序集合,第二个部分为无序集合,那么此时有序集合是空的[],而无序集合为[2,1,5,3,7],通过依次遍历原集合([2,1,5,3,7])的每一个元素记为A,循环的每个元素都去和无序集合里的每个值(遍历无序集合)进行对比,找到当次无序集合里的最小值(需要遍历此时的无序集合)B,然后交换A和B的位置,这样B就能进入到有序集合,A被交换到了无序集合里.具体过程如下:

  1. 开始遍历原集合(此时有序集合为[],无序集合为[2,1,5,3,7]),将集合中的第1个元素取出[2],然后开始和剩下的无序集合([1,5,3,7])进行对比,不和全部无序集合对比是因为自身和自身对比没意义,所以我们从无序集合的第2个开始进行比大小,我们找到了[1,5,3,7]里的[1],然后进行交换(2和1进行交换),此时原集合变为[1,2,5,3,7]

  2. 此时遍历出集合第2个元素(此时有序集合为[1],无序集合为[2,5,3,7]),将无序集合中的第1个元素取出[2] (因为被交换所以第2次又是2,例子没选好,懒得改了),然后开始和剩下的无序集合([5,3,7])进行对比,我们从此时的无序集合[2,5,3,7]的第2个开始进行比大小,我们发现[2,5,3,7]里没有比2还小的元素了,所以不用进行交换,因为此时的2就是这一轮最小的元素,此时原集合变为[1,2,5,3,7]

  3. 此时遍历出集合第3个元素(此时有序集合为[1,2],无序集合为[5,3,7]),将无序集合中的第一个元素取出[5] ,然后开始和剩下的无序集合([3,7])进行对比,我们从此时的无序集合[5,3,7]的第二个开始进行比大小,我们找到了[3,7]里比5还小的元素[3],所以两个进行交换,此时原集合变为[1,2,3,5,7]

  4. 此时遍历出集合第4个元素(此时有序集合为[1,2,3],无序集合为[5,7]),将无序集合中的第一个元素取出[5] ,然后开始和剩下的无序集合([7])进行对比,我们从此时的无序集合[5,7]的第二个开始进行比大小,我们发现[7]里没有比5还小的元素了,所以不用进行交换,因为此时的5就是这一轮最小的元素,此时原集合变为[1,2,3,5,7]

  5. 此时遍历出集合第5个元素(此时有序集合为[1,2,3,5],无序集合为[7]),将无序集合中的第一个元素取出[7] ,然后开始和剩下的无序集合([])进行对比,我们从此时的无序集合已经是空集合了,所以不用进行交换,因为此时的7就是这一轮最小的元素,此时原集合变为[1,2,3,5,7]

  6. 此时集合已经排序完毕,排序结果就是最后的有序集合[1,2,3,5,7],无序集合里已经没有元素了.

原理

通过例子可以看出,集合有多少个元素就得遍历多少遍,所以需要第1个关键值,记录遍历集合的游标(记为i),在遍历元素的同时需要去找当前无序集合里的最小值,所以还需要2个关键游标,当前最小元素的游标(k),无序集合里的游标(j). 通过遍历集合我们先获取到当前 默认最小元素的游标 k 的值, 然后在无序集合遍历寻找比 k 的值 还小的值,把无序集合的当前的j赋值给k一直更新到无序集合遍历完毕, 这个时候如果 k 不等于初始值了,说明无序集合里有最小值的出现,交换k(已经更新为无序集合里最小值的游标)和i(第1层遍历的游标)的值,然后游标i进入下一轮的循环.

代码

1
2
3
4
5
6
7
8
9
def selectSort(list: 'list') -> list:
for i in range(len(list)): #循环目标列表,此时的i为遍历集合的游标
k = i #把当前游标选为默认的最小元素的游标
for j in range(i+1, len(list)): #用k的值,去和当前无序集合里的每一个值进行对比,所以要循环此时的无序集合,因为无序集合里的第一个和游标i的值相等,所以没有进行比大小的意义,所以循环是从无序集合里的i+1开始
if list[j] < list[k]: #进行k的值和无序集合里j的值比大小
k = j #如果发现无序集合里有更小的,那就更新k的值(k是每轮当中最小值的游标,初始值是和无序集合里第1个相等)
if k != i: #如果k的最终值已经和k的初始值i不一致了,说明无序集合里有最小值
list[k],list[i] = list[i], list[k] #那么就要交换2个游标的值
return list #返回排好序的list

总结

空间复杂度为O(1),因为是在原数组内进行不断的交换,没有额外的空间占用.时间复杂度为O(n²),因为有嵌套循环,抛去常数后为n²的复杂度.直接选择排序只需要好好理解游标的概念即可.

Bowen wechat
博客文章会同步更新在公众号[后端浪里个浪]
一毛也是爱~