发现了一个网站可以更好的帮助理解排序的过程:点这里查看
插入排序
保持第一个位置不动,后面位置上的元素比前面小,则交换,换一轮,则第一个位置上的元素就是最小的了
继续保持第二个位置上元素不动,接着比较其后面的元素
num=[78,54,443,32,65,654,234,232]
for i in range(1,len(num)):
minNum= num[i]#默认当前num[i]为最小值
index=i#记录最小值索引
for j in range(i-1,-1,-1):#从后往前循环遍历
if num[j] > minNum:#如果当前值大于最小值,当前值后移,同事更新最小值索引
num[j+1]=num[j]
index=j
else:
break
num[index]=minNum#最后把最小值放记录索引处
print(num)
选择排序
选择排序
选择排序是每次循环当前数字和后面的数字挨个比较,记住最小数字的索引值,最后把当前数字和最小索引的数字交换,进行下一次循环
list=[200,4,65,76,2,3,65,9,54523,4,323,212]
for i in range(len(list)):
minnum = i
for j in range(i+1,len(list)):
if list[j] < list[minnum] :
minnum=j
list[i],list[minnum] = list[minnum],list[i]
print(list)
优化–二元选择排序
既然每次可以找到最小值的索引,那么同理也可以找到最大值的索引,把最小值和无序列表第一个值交换,最大值和无序列表最后一个值交换,这样可以大量减少循环的次数
num=[4,5,1]
for i in range(len(num)//2):#因为每次找到两个值,所以循环次数减半,
#列表长度为奇数时,中间的值无需交换
maxindex = -i-1#增加最大值索引,默认无序列表中最后一项(使用负索引,从后往前)
minindex = i
for j in range(i+1,len(num)-i):内层循环每次前后各推进一个数放入有序序列
if num[-j-1]>num[maxindex]:
maxindex=-j-1
if num[j]<num[minindex]:
minindex=j
if num[maxindex] == num[minindex]:#如果最大值和最小值相等,说明列表元素都相等,无需交换--判断特殊情况
break
if num[maxindex]!=num[-i-1]:
num[maxindex],num[-i-1]=num[-i-1],num[maxindex]
if num[-i-1]==num[minindex]:#此处做了一个判断,如果减缓最大值时交换的对象为最小值,此时调整最小值的索引
minindex=maxindex
if minindex != i and num[minindex] != num[i]:#此处增加判断:如果索引不同但值相同,就不需要交换
num[minindex],num[i]=num[i],num[minindex]
print(num)
选择排序总结:
1、没有办法知道当前轮是否已经达到排序要求,但可以知道极值是否在目标索引位置上,遍历次数为1,。。。n-1之和n(n-1)/2,时间复杂度为O(n²);
2、因为减少了交换次数提高了效率,所以性能上要略好于冒泡法。