简单选择排序
- 属于选择排序
- 两两比较大小;找出极值(极大值或极小值)被放置在固定的位置,这个位置一般指的是某一端
- 结果分为升序和降序排序
- 降序
n个数从左至右,索引从0开始到n-1,两两一次比较,记录最大值索引,此轮所有数比较完毕,将最大数和索引0数交换,如果大数就是索引1,不交换。第二轮,从1开始比较,找到最大值,将它和索引1位置交换,如果它就在索引1位置则不交换。以此类推,每次左右都会固定下一个大数。 - 升序
和降序相反
简单选择排序代码实现(一)
- 将1-9随机打乱后,从大到小排序
#解析版
nums = list(range(10))# 生成0~9的十个数
import random #导入模块
random.shuffle(nums) # 导入shuffle随机生成树模块,将该列表随机打乱
print(nums) #打印出随机打乱列表后的效果
length = len(nums) #计算长度
count_iter = 0 #计算迭代次数
count_swap = 0 #计算交换次数
#选择排序
for i in range(length): # 迭代从0开始
maxindex = i # 默认迭代第一次是数就是最大值,即索引为0为最大值
for j in range(i+1, length): # 迭代从1开始
count_iter += 1
if nums[j] > nums[maxindex]: #当maxindex即i=0,j=1~9,
maxindex = j #,如果索引为j大于索引为maxindex,则最大值即maxindex=j,变为索引为j
if i != maxindex: #如果上述if语句有成立,则证明maxindex有变过,即i != maxindex
nums[i], nums[maxindex] = nums[maxindex], nums[i] #两个索引位置的元素交换
count_swap +=1
print(nums, count_iter, count_swap) #打印打印出排好序的列表,迭代和交换过的次数
#纯净版
nums = list(range(10))
import random
random.shuffle(nums)
print(nums)
length = len(nums)
for i in range(length):
maxindex = i
for j in range(i+1, length):
if nums[j] > nums[maxindex]:
maxindex = j
if i != maxindex:
nums[i], nums[maxindex] = nums[maxindex], nums[i]
print(nums)
简单选择排序代码实现(二)
优化实现 二元选择排序
同时固定左边最大值和右边最小值
优点:减少迭代元素的次数
#解析版
nums = list(range(10))# 生成0~9的十个数
import random #导入模块
random.shuffle(nums) # 导入shuffle随机生成树模块,将该列表随机打乱
print(nums) #打印出随机打乱列表后的效果
length = len(nums) #计算长度
count_iter = 0 #计算迭代次数
count_swap = 0 #计算交换次数
for i in range(length // 2): #length // 2 整除,因为一轮循环同时确定了左右两个极值,所以i=[0,1,2,3]
maxindex = i # 默认迭代第一次是数就是最大值,即索引为0为最大值
minindex = -i - 1 # 默认迭代第一次是数就是最小值,即索引为-1为最小值
minorigin = length + minindex # 将负索引转换为正索引
for j in range(i+1, length-i): #当i=0,j=[1~9);当i=1,j=[2~8),当i=3,j=[4,6)
count_iter += 1
if nums[j] > nums[maxindex]: #第一次当i=0,j取[1~8)
maxindex = j #如果索引为j大于索引为maxindex,则最大值即maxindex=j,变为索引为j
if nums[-j -1] < nums[minindex]: #第一次当i=0,j取[1~8),-j -1 = -2,即索引[-2]与[-1]比较
minindex = -j - 1 # 如果有发现比索引[minindex]还小的,则进行交换.
if nums[maxindex] == nums[minindex]: braek #元素都相同
if i != maxindex: #如果上述if nums[j] > nums[maxindex] 语句有成立,则证明maxindex有变过,即i != maxindex
nums[i], nums[maxindex] = nums[maxindex], nums[i] #两个索引位置的元素交换
count_swap += 1
if i == minindex:
minindex = maxindex #修正索引,
if minindex != minorigin and nums[minorigin] != nums[minindex]:
# 索引不同,但是值相同,没有必要交换
nums[minorigin], nums[minindex] = nums[minindex], nums[minorigin] #两个索引位置的元素交换
#count_swap += 1
print(nums, count_iter, count_swap)
# 纯净版
nums = list(range(10))
import random
random.shuffle(nums)
print(nums)
length = len(nums)
for i in range(length // 2):
maxindex = i
minindex = -i - 1
minorigin = length + minindex
for j in range(i+1, length-i):
if nums[j] > nums[maxindex]:
maxindex = j
if nums[-j -1] < nums[minindex]:
minindex = -j - 1
if nums[maxindex] == nums[minindex]: braek
if i != maxindex:
nums[i], nums[maxindex] = nums[maxindex], nums[i]
if i == minindex:
minindex = maxindex
if minindex != minorigin and nums[minorigin] != nums[minindex]:
nums[minorigin], nums[minindex] = nums[minindex], nums[minorigin]
print(nums)
总结
- 简单选择排序需要数据一轮轮比较,并在每一轮中发现极值
- 没有办法知道当前轮是否已经达到排序要求,但是可以知道极值是否在目标索引位置上
- 遍历次数1,…,n-1之和n(n-1)/2
- 时间复杂度O(n²)
- 减少了交换次数,提高了效率,性能略好于冒泡法