算法之冒泡排序与选择排序

如何将一个无序的数组变成从大到小或从小到大的排列?这可以用冒泡排序法与选择排序法,两者的区别并不算很大。

1.冒泡排序法:

算法描述:通过嵌套循环,比较两个数,再通过交换位置把两个数从不符合排列顺序变成符合排列顺序。
假定要从小到大排序:

#通过两次循环来使得一个序列排序,内循环进行比较两个元素,并交换两个元素的位置,使得更大的元素在后面
ls=[32,231,43,123,3465,9,32421,45,68,2,90,123,56,79876,1290,98]
i=0
while i<len(ls):
    j=0#
    while j<len(ls):
        if ls[i]<ls[j]:#外循环比内循环的数大则交换
            ls[i],ls[j]=ls[j],ls[i]
            #交换位置
        j+=1
    i+=1
print(ls)

打印出结果

C:\python3.8\PyCharmLocation\venv\Scripts\python.exe C:/python3.8/PyCharmLocation/venv/7/23/bubbleSort.py
[231, 32, 43, 123, 3465, 9, 32421, 45, 68, 2, 90, 123, 56, 79876, 1290, 98]
[3465, 32, 43, 123, 231, 9, 32421, 45, 68, 2, 90, 123, 56, 79876, 1290, 98]
[32421, 32, 43, 123, 231, 9, 3465, 45, 68, 2, 90, 123, 56, 79876, 1290, 98]
[79876, 32, 43, 123, 231, 9, 3465, 45, 68, 2, 90, 123, 56, 32421, 1290, 98]
[32, 79876, 43, 123, 231, 9, 3465, 45, 68, 2, 90, 123, 56, 32421, 1290, 98]
[9, 43, 123, 231, 79876, 32, 3465, 45, 68, 2, 90, 123, 56, 32421, 1290, 98]
[9, 32, 123, 231, 79876, 43, 3465, 45, 68, 2, 90, 123, 56, 32421, 1290, 98]
......
[2, 9, 32, 43, 45, 56, 68, 90, 98, 123, 123, 231, 1290, 3465, 79876, 32421]
[2, 9, 32, 43, 45, 56, 68, 90, 98, 123, 123, 231, 1290, 3465, 32421, 79876]
[2, 9, 32, 43, 45, 56, 68, 90, 98, 123, 123, 231, 1290, 3465, 32421, 79876]

Process finished with exit code 0

从结果可以看到,虽然判断条件是 if ls[i]<ls[j]:#外循环比内循环的数大则交换,最终把最大的数给了0号位,但接下来,第二次外循环,1号位比0号位小,接过了0号位的最大数…依次传递,最终把最大数传给了末尾。
如果没有经过演算,那 这个判断条件看起来似乎不太对,居然把最大的数拿到了最前面而不是最小的,在这里举一个栗子:
如同有一个队伍16个人,16个大小不一的钱袋,一人一份钱袋,现在要从小到大排序,通过从队伍头到尾顺序交换钱袋的方法,第一个人先与第二个人比较钱袋,选择是否交换,然后与第三个人比较钱袋大小,进行选择交换,一直到与第16个人比较,第一个人拿走了最大的钱袋。结束第一个人的循环回合。
现在轮到第二个人的循环回合,2号位与1号位比较,交换1号位最大的钱袋,继续比较,发现其余的人的钱袋都比这个小,就没有再交换。
第三个人的回合,他把小钱袋换给了1号位,再与2号位比较,通过交换,拿走了2号位的最大钱袋…
最终,最大的钱袋被第16个人拿走了。
可以看出,后面的人把自己的小钱袋交换给1号位,直到1号位拿到了最小的钱袋,然后后面的人就把自己的小钱袋交换给2号位,直到2号位拿到了只比1号位大一点的钱袋…当其拿到最大的钱袋时,就不再交换。最终,1号位拿到了最小的钱袋,最后一个人拿到了最大的钱袋,其余也从大到小依次排序。

2.选择排序法:

算法描述:也是通过嵌套循环比较,在内层循环比较出最小/大的数,将其余下标0号位交换,再从剩下的数列中比较出最小的交换到下标1号位,依次循环,直到结束。

l=[32,231,43,123,3465,9,32421,45,68,2,90,123,56,79876,1290,98]

for i in range(len(l)):
    mind=i#把第一位赋给装最小的数的容器
    for j in range(i+1,len(l)):#每次都缩小一个位置
        if l[mind]>l[j]:#比较出最小数的下标
            mind=j
    if mind==i:#刚好第一位就是最小的数,则不改变其位置
        pass
    else:
        l[i],l[mind]=l[mind],l[i]# 第一位不是最小的数,与容器交换下标
print(l)

结果如下:

C:\python3.8\PyCharmLocation\venv\Scripts\python.exe 
[2, 9, 32, 43, 45, 56, 68, 90, 98, 123, 123, 231, 1290, 3465, 32421, 79876]

Process finished with exit code 0

这里最重要的是:第二层的循环条件,是i+1,这样每次启动内循环,其值域范围都会缩小一个位置,而这个位置就是在前排用来存储最小值的位置。

3.选择排序法和冒泡排序法的不同:

在时间复杂度方面看来,冒泡排序法比选择排序法需要更多的时间,虽然同样是嵌套循环,但选择排序法的内循环次数一次比一次少,而冒泡排序法的内循环每次都是一样的次数,同样,空间的开销也就更小了一点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值