选择排序及其Python实现【算法图解】
1. 引出问题
假设你的手机中存储了很多乐曲,对于每个乐队,你都记录了其作品被播放的次数。
乐队 | 播放次数 |
---|---|
RADIOHEAD | 156 |
KISHOKE KUMAR | 141 |
THE BLACK KEYS | 35 |
NEUTRAL MILK HOTEL | 94 |
BECK | 88 |
THE STROKES | 61 |
WILCO | 11 |
你想将乐队按照播放次数从多到少进行排列,从而将你喜欢的乐队排序,怎么做呢?
2. 选择排序
最简单的办法就是,我们从列表中选择出播放次数最多的乐队,将其转移到一个新列表中:
乐队 | 播放次数 | 👉 | 乐队 | 播放次数 |
---|---|---|---|---|
RADIOHEAD | 156 | RADIOHEAD | 156 | |
KISHOKE KUMAR | 141 | |||
THE BLACK KEYS | 35 | |||
NEUTRAL MILK HOTEL | 94 | |||
BECK | 88 | |||
THE STROKES | 61 | |||
WILCO | 11 |
这里为了确定最大播放量,我们需要检查所有的元素n=7。
再次进行同样的操作,找出播放量第二的乐队,将其转移到新列表中:
乐队 | 播放次数 | 👉 | 乐队 | 播放次数 |
---|---|---|---|---|
RADIOHEAD | 156 | |||
KISHOKE KUMAR | 141 | KISHOKE KUMAR | 141 | |
THE BLACK KEYS | 35 | |||
NEUTRAL MILK HOTEL | 94 | |||
BECK | 88 | |||
THE STROKES | 61 | |||
WILCO | 11 |
这次我们检查了n-1=6个元素。
继续这样,我们共执行n=7次这样的操作,可以得到一个有序的列表:
乐队 | 播放次数 | 👉 | 乐队 | 播放次数 |
---|---|---|---|---|
RADIOHEAD | 156 | |||
KISHOKE KUMAR | 141 | |||
NEUTRAL MILK HOTEL | 94 | |||
BECK | 88 | |||
THE STROKES | 61 | |||
THE BLACK KEYS | 35 | |||
WILCO | 11 |
这里,我们即完整的展现了一次选择排序的算法流程
我们共执行了多少次元素检查呢?这是一个等差数列:n,n-1,n-2,…,2,1;
求和很简单,套公式:sum=n×(n+1)/2=n²/2+n/2
,在用大O表示法表示时,因1/2是常数,直接省略,n相对于n²是小量,省略。
因此,选择的排序的运行速度为:O(n²)
3. Python代码(降序排列)
键入以下代码并运行:
## findSmallest函数作用:找到一个列表中的最小值
## 输入:
## arr:传入的列表
## 输出:
## smallestIndex:最小值在列表中的索引位置
def findSmallest(arr):
smallest=arr[0] # 初始化最小值为列表的第一个值
smallestIndex=0 # 列表的第一个值索引为0
for i in range(1,len(arr)): # 遍历列表索引,从1到末尾
if smallest>arr[i]: # 如果当前最小值比列表中的值大,那么更新最小值和索引
smallest=arr[i]
smallestIndex=i;
return smallestIndex # 完成遍历后,返回最小值索引
## selectSort函数作用:执行选择排序,升序排列
## 输入:
## arr:传入的列表
## 输出:
## newArr:排序完成的列表
def selectionSort(arr):
newArr=[] # 初始化输出列表
for i in range(len(arr)): # 遍历列表,找到最小值,放入新列表
smallest=findSmallest(arr)
newArr.append(arr.pop(smallest)) # 在原来的列表中弹出最小值,转移到新列表中
return newArr # 完成遍历后,输出列表
## 测试代码
print(selectionSort([156,141,94,88,61,35,11]))
这里代码中的注释比较清楚,因此不再赘述,结果如下:
4. 更快的实现(快速排序)
选择排序比较灵巧,但是执行速度较慢。
快速排序是一种更快的算法,其运行时间为O(n×log n),有兴趣可以看看:快速排序