2. python 冒泡排序-全网最详细

【目录】


【正文】

2. python 冒泡排序-全网最详细

学习时间:30分钟,难!

1. 什么是冒泡排序

冒泡排序(Bubble Sort)法可以理解成升序排序,即排列顺序是由小到大

Bubble [ˈbʌbl]:冒泡。
Sort [sɔːt]:分类。

【实现原理】

从头开始比较每一对相邻的元素,每一轮选出一个最大的数放到序列最后,重复遍历序列,直到完成升序排列。

这句话有3个重点:

  • 从头开始
  • 比较的是相邻的数
  • 最大的数放到最后

之所以叫做冒泡排序,是因为每一个元素都可以像小气泡一样,根据自身大小一点一点向数组的一侧移动。

大的数向后移,小的数向前移。

冒泡排序的核心就是2个数相比较,大的数往后移

2. 实现过程分析

2.1 2个元素比较

a = [4,2]

对上面的列表进行冒泡排序,过程如下:

列表的第1个元素4和第2个元素2比较:4>2,交换位置,结果为[2,4]。

列表中最大的数4已经排在最后,元素比较结束,冒泡排序完成。

【总结】

  • 2个元素比较1次可完成升序排序。
  • 列表元素的比较顺序如下:
  • 0-1

【备注】

这里的0和1是列表的索引。
列表的索引0对应列表的第1个元素。
列表的索引1对应列表的第2个元素。

2.2 3个元素比较

a = [8,4,2]

第1轮排序,选出最大的数8

【第1次比较】

列表的起始顺序:[8,4,2]

第1个元素8和第2个元素4比较:8>4,交换位置,当前列表顺序[4,8,2]。

【第2次比较】

当前列表顺序[4,8,2]

新列表第2个元素8和第3个元素2比较:8>2,交换位置,当前列表顺序[4,2,8]。

此时,第一轮排序结束,选出最大的数8。

第2轮排序,选出最大的数4

【第3次比较】

第2轮排序时8已经是最大的数,位置固定,不在参与排序游戏。

当前列表顺序[4,2,8]

新列表的第1个元素4和第2个元素2比较:4>2,交换位置,当前列表顺序[2,4,8]。

【总结】

  • 2个元素比较1次。

  • 比较顺序如下:

  • 0-1

  • 3个元素比较3次。

  • 比较顺序如下:

  • 0-1

  • 1-2

  • 0-1

2.3 4个元素比较

a = [8,4,2,0]

第1轮排序,选出最大的数8

【第1次比较】

当前列表顺序:[8,4,2,0]

第1个元素和第2个元素比较:8>4,交换位置,当前列表顺序[4,8,2,0]。

【第2次比较】

当前列表顺序[4,8,2,0]

第2个元素和第3个元素比较:8>2,交换位置,当前列表顺序[4,2,8,0]。

【第3次比较】

当前列表顺序[4,2,8,0]

第3个元素和第4个元素比较:8>0,交换位置,当前列表顺序[4,2,0,8]。

4个元素经过3次循环可选出最大的数8。

8的位置固定不在参与排序游戏,还有3个数参与游戏。

第2次排序,选出第2大的数

【第4次比较】

3个数选出最大的数,需要2次比较。

当前列表顺序[4,2,0,8]

第1个元素和第2个元素比较:4>2,交换位置,当前列表顺序[2,4,0,8]。

【第5次比较】

当前列表顺序[2,4,0,8]

第2个元素和第3个元素比较:4>0,交换位置,当前列表顺序[2,0,4,8]。

此时4的位置固定,不再参与游戏。

第3次排序,选出第3大的数

【第6次比较】

2个数选出最大的数,只需1次比较。

当前列表顺序[2,0,4,8]

第1个元素和第2个元素比较:2>0,交换位置,当前列表顺序[0,2,4,8]。

每个数都找到自己的位置,游戏结束。

【总结】

  • 2个元素比较1次。

  • 比较顺序如下:

  • 0-1

  • 3个元素比较3次。

  • 比较顺序如下:

  • 0-1

  • 1-2

  • 0-1

  • 4个元素比较6次。

  • 比较顺序如下:

  • 0-1

  • 1-2

  • 2-3

  • 0-1

  • 1-2

  • 0-1

3. 课堂练习

请你思考5、6个元素分别需要比较几次,并写出列表的索引比较顺序。

冒泡排序就是每次选出一个最大的值,将最大值淘汰不参与剩下的游戏,因此每一轮循环淘汰1个元素:

2个元素的比较次数:1,循环1次
3个元素的比较次数:2+1 ,循环2次
4个元素的比较次数:3+2+1,循环3次
5个元素的比较次数:4+3+2+1,即循环4次
6个元素的比较次数:5+4+3+2+1 ,即循环5次

冒泡排序是从头开始比较,因此每一次循环比较都从索引0开始。
比较的是相邻的元素,因此后1个索引都比前1个索引多1。
每次都淘汰一个元素,因此每次都少一对索引比较。
因为每次循环只能选出一个最大的数,因此n个元素就需要循环n-1次。

  • 5个元素比较10次。
  • 比较顺序如下:
  • 0-1
  • 1-2
  • 2-3
  • 3-4
  • 0-1
  • 1-2
  • 2-3
  • 0-1
  • 1-2
  • 0-1

4. 循环代码

冒泡排序的代码难点在于循环的实现,下面我们先完成循环部分的代码。

0-1,1-2,2-3这样每个数都比前一个数多1的循环我们通常用一个for循环就能实现。

  • 3个元素比较3次。
  • 0-1
  • 1-2
  • 0-1

而像上面这样的上下2个数的值有增有减,我们通常考虑for循环嵌套。

  • 0-1
  • 1-2

前2行是递增的。

  • 1-2
  • 0-1

第2行到第3行是递减的。

有增又有减,那通常是用嵌套循环来实现的。

因为我们最终要编写自定义函数来实现冒泡排序,此时数组的元素个数是个动态值。
因此我们通常要将元素的个数加入for循环。
这种思路在实战中经常要用到。

【外循环】

2个元素的比较次数:1
3个元素的比较次数:2+1
4个元素的比较次数:3+2+1
5个元素的比较次数:4+3+2+1
6个元素的比较次数:5+4+3+2+1

  • 3个元素比较3次。
  • 0-1
  • 1-2
  • 0-1

我们以3个元素为例,3个元素比较3次,外循环可以先试写成如下代码:

# 这里的3是元素的个数:
for j in range(3):
    print(j)

【终端输出】

0
1
2

【内循环】

  • 3个元素比较3次。

  • 0-1

  • 1-2

  • 0-1

  • 0-1

  • 1-2

第1次内循环要得到上面的数,需要循环2次,那range的值只能取到2,又同时需要把j的值带到内循环控制循环次数。
j=0的时候,3-j-1=2
我们可以先试着把循环代码写成下面这样:

# 这里的3是元素的个数:
for j in range(3):
    for i in range(3-1-j):
        print(i,i+1)

【终端输出】

0 1
1 2
0 1

【用4个元素检验循环代码】

# 这里的4是元素的个数:
for j in range(4):
    for i in range(4-1-j):
        print(i,i+1)

【终端输出】

0 1
1 2
2 3
0 1
1 2
0 1

【思路总结】

编写循环代码有以下几个要点:

  • 通常需要把动态值加入range函数来控制循环次数。
  • 需要查看规律确定外循环和内循环。
  • 在不会分析规律的时候用简单的数字带入不断试错也能写出。
  • 我现在也经常用数字带入试错的方法编写for循环。

5. 多个变量赋值

a = 3
b = 4

上面是我们学过的变量赋值法,每行代码给一个变量赋值。

为了使代码更简洁,Python也提供用一行代码完成多个变量的赋值。

a,b = 3, 4
print(a)
print(b)

【终端输出】

3
4

a,b = 3, 4表示把3赋值给变量a,把值4赋值给变量b

变量与变量之间,值与值之间用英文逗号,分隔。

a,b,c= 3, 4, 5
print(a)
print(b)
print(c)

【终端输出】

3
4
5

【变量互换值】

a = 3
b = 4
a,b = b,a
print(a)
print(b)

【终端输出】

4
3

a的初始值是3,b的初始值是4。
a,b = b,a表示把a b的值互换。

a,b = b,a

等价于:

a=b 
b=a

6. 元素交换

文章的开篇我们说过冒泡排序每一轮选出一个最大的数放到序列最后,那如何实现将元素放到最后的呢?

我们首先需要需要个if条件判断语句进行大小判断,如果前面的数大于后面的数那2个数通过变量赋值互换位置,如果小于等于则不执行互换位置代码。

【2个元素】

a = [4,2]
if a[0] > a[1]:
    a[0],a[1]=a[1],a[0]
print(a)

【终端输出】

[2, 4]

【代码解析】

a = [4,2]

自定义一个列表,列表含有2个元素。

if a[0] > a[1]:

列表名[索引]是列表索引取值法,根据列表的索引号取值。
a[0] 取到列表的第1个元素4
a[1] 取到列表的第1个元素2
如果列表的第1个元素的值大于第2个元素的值。

a[0],a[1]=a[1],a[0]

上面的代码实现了列表元素位置的互换。
如果列表的第1个元素的值大于第2个元素的值,
将原始列表a[1]的值赋值给新列表a[0]。
将原始列表a[0]的值赋值给新列表a[1]。

如果列表的第1个元素的值不大于第2个元素的值,
那后面的代码将不运行,列表的值不互换。

通过值的互换实现了元素位置互换。

7. 冒泡排序综合代码

【完整的冒泡排序代码示例】

def mao_pao(num_list):
    num_len = len(num_list)
    for j in range(num_len):        
        for i in range(num_len - 1 - j):
            if a[i] > a[i+1]:
                a[i], a[i+1] = a[i+1], a[i]                			
if __name__ == '__main__':
    # 换成实际要排序的数组
    a = [8,4,0,2]
    mao_pao(a)
    print(a) 

【终端输出】

[0, 2, 4, 8]

【代码解析】

def mao_pao(num_list):
  • def自定义一个函数
  • 函数名为mao_pao
  • 接收的参数为num_listnum_list是实际要排序的数组,调用函数时要传入的参数。
  • 注意自定义函数后需要跟一个英文冒号:
num_len = len(num_list)
  • len函数统计元素的个数,传入的是列表则统计的是列表的元素个数。
  • num_len就是代码元素个数。
for j in range(num_len):

外循环,控制循环的次数。

for i in range(num_len - 1 - j):

内循环,控制循环的比较次数。

if a[i] > a[i+1]:
    a[i], a[i+1] = a[i+1], a[i] 
  • if条件判断语句比较相邻两个元素的值。

  • 如果结果是大于,2个元素互换位置。

  • 结果是小于或等于,不执行元素互换位置的代码。

if __name__ == '__main__':

85. if name == "main"的作用和原理(适合小白)

a = [8,4,0,2]

这是要进行排序操作的对象。

mao_pao(a)
  • 调用函数,mao_pao是函数名。
  • a是要操作的对象,a的值传递给自定义函数中的num_list
print(a) 

最后输出排序后的列表。

为了方便初学者掌握运行过程,我多加2个print,代码如下:
【代码示例】

def mao_pao(num_list):
    num_len = len(num_list)
    for j in range(num_len):        
        for i in range(num_len - 1 - j):
            if a[i] > a[i+1]:
                a[i], a[i+1] = a[i+1], a[i]
            # 输出进行比较的列表索引
            print(i,i+1)                			
if __name__ == '__main__':
    # 换成实际要排序的数组
    a = [8,4,0,2]
    mao_pao(a)
    print("最终的排序结果:",a) 

【终端输出】

0 1
1 2
2 3
0 1
1 2
0 1
最终的排序结果: [0, 2, 4, 8]

【代码示例】

def mao_pao(num_list):
    x = 0
    num_len = len(num_list)
    for j in range(num_len):        
        for i in range(num_len - 1 - j):            
            if a[i] > a[i+1]:
                a[i], a[i+1] = a[i+1], a[i]
            x += 1
            # 输出每一次排序后的列表
            print(f"第{x}次排序结果",a)                			
if __name__ == '__main__':
    # 换成实际要排序的数组
    a = [8,4,0,2]
    mao_pao(a)
    print("最终的排序结果:",a) 

【终端输出】

第1次排序结果 [4, 8, 0, 2]
第2次排序结果 [4, 0, 8, 2]
第3次排序结果 [4, 0, 2, 8]
第4次排序结果 [0, 4, 2, 8]
第5次排序结果 [0, 2, 4, 8]
第6次排序结果 [0, 2, 4, 8]
最终的排序结果: [0, 2, 4, 8]
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值