冒泡排序
- 属于交换排序
- 两两比较大小,交换位置
- 结果分为升序和降序排序
升序
- n个数从左到右,从第一位开始与后面一位比较
- 如果前面的数字大于后面的数字交换位置,如果前面的数字不大于后面的数字不交换位置
- 第二位数字与第三位数字比较, 如果前面的数字大于后面的数字交换位置,如果前面的数字不大于后面的数字不交换位置
- 直到比较到最后一位数字比较完成,最后一位数字是所有数字中最大的一个
- 再从第一位开始比较,选出最大放在有序区,也就是倒数第二位。
- 在无序区中循环刚才的操作,随着循环次数的增加,无序区数字数目减小,有序区数字数目增大。直至无序区没有数字
降序
冒泡排序属于交换排序,n个数从右向左,两两交换比较大小,一开始所有数字无序排放可以看作一个无序区,最后一位数字,与倒数第二位数字比较,若效小于第二位数字,则交换位置,否则保持原样,倒数第二位与倒数第三位数比较,若倒数第二位小于倒数第三位,则交换位置,否则保持原样,按照这种交换规则比较完第一位数字。
这时候第一位是所有数字中最小的,同时可以看作有序区形成,无序区数字数目减少。再次从无序区进行相同的比较,选出第二小的数字,追加到有序区后面,这样有序区一直在增加,无序区减少,直到无序区没有数字可以比较。
代码实现
ll=[1,2,3,4,2,2,3]
for i in range(1,len(ll)):
flag=True #定义一个参数
for j in range(1,len(ll)-1):
if ll[j]<ll[j-1]:
ll[j-1],ll[j]=ll[j],ll[j-1]
flag=False #如果不执行交换就不改变值
if flag==True: #不执行交换就跳出执行
break
print(ll)
冒泡法
- 冒泡法需要数据一轮轮比较
- 可以设定一个标记判断此轮是否有数据交换,如果没有发生交换,可以结束排序,如果发生交换,继续下一轮排序
- 最差的排序情况,初始顺序与目标顺序完全相反,遍历次数1,2,……n-1之和n(n-1)/2
- 最好的情况,初始顺序与目标顺序完全相同,遍历n-1
- 时间复杂度为O(n^2)
简单选择排序
- 属于选择排序
- 两两比较大小,找出极值(极大值或极小值)被放置在固定的位置,这个固定位置一般指的是某一端
- 结果分为升序和降序排列
升序
n个数,从左到右,索引从0到n-1,两两依次比较,记录大值索引,此轮所有数比较完毕后,将大值索引和最后一位数交换位置,如果最大索引为n-1则不交换。以此类推,每次右边都会得到一个大数。
降序
n个数从左到右,索引从左到右,是一个无序区,两两依次比较,记录大值索引,将大值与索引0数交换位置,有序区形成,第二轮从索引1位置开始,记录最大值索引,与索引1交换位置,以此类推,每次有序区都会得到一个最大值,无序区都会减少一个数字。
for i in range(len(ll)):
a=0
for j in range(len(ll)-i):
if a<ll[j]:
a=j
if a!=(-i-1): #如果索引记录的位置正好是无序区末尾的索引
ll[a],ll[-i-1]=ll[-i-1],ll[a]
print(ll)
简单选择排序总结
- 简单选择排序需要数据一轮轮比较,并在每一轮中发现极值
- 没有办法知道当前轮是否已经达到排序要求,但是可以知道极值是否在目标索引位置上
- 遍历次数1,……,n-1之和n(n-1)/2
- 时间复杂度O(n^2)
直接插入排序
直接插入排序原理
- 在未排序序列中,构建一个子序列排序,直至全部数据排序完成
- 将待排序的数,插入到已经排序的序列中合适位置
- 增加一个哨兵,放入待比较值,让它和后面已经排序的序列比较,找到合适的插入点