冒泡排序优化 | 学习笔记

简介: 快速学习 冒泡排序优化

开发者学堂课程【Python入门 2020年版冒泡排序优化】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/639/detail/10301


冒泡排序优化


内容介绍

一、练习题讲解

二、冒泡排序优化


一、练习题讲解

课后题一

#有一个列表 names,保存了一组姓名 names=[ " zhangsan ' , ' lisi ' , ' chris ' , ' jerry ' , 'henry ' ]

#再让用户输入一个姓名,如果这个姓名在列表里存在,提示用户姓名已存在;

#如果这个姓名在列表里不存在,就将这个姓名添加到列表里。

答案:

1.使用 in 运算符

names=[ 'zhangsan ' , ' lisi ' , ' chris ' , ' jerry ' , 'henry ' ]

//列出列表中的元素

username = input ( ‘ 请输入一个用户名: )

//提示输入用户名,赋给变量 username

if username in names: //如果 username names

print(‘用户名已经存在’)//显示已经存在

else:  //如果不在

names.append(username)

//将输入的 username 加进列表中去

2. 使用遍历

l  错误写法

names=[ ' zhangsan ' , ' lisi ' , ' chris ' , ' jerry ' , 'henry ' ]

//列出列表中的元素

username = input ( ‘ 请输入一个用户名: )

for name in names:

if username == name

print(‘用户名已经存在’)

break

else:     //else if 对齐会使得,执行了 if 就随之执行 else

names.append(username)   //就会错误的添加多余数据

print(names)

此时不能将 else if 相对应,因为当输入 lis i时,处于第一次循环,输出的元素是与第一个元素 zhangsan 进行比较的,在 if 判断时两者不相等,若写成当前的 else 格式则会把 lisi 加进列表中,但其实列表中下一次循环含有 lisi

所以我们应该改成 for else 相对。变为当 for 循环退出之后,再执行 else

正确写法(else for 对齐)

names=[ ' zhangsan ' , ' lisi ' , ' chris ' , ' jerry ' , 'henry ' ]

//列出列表中的元素

username = input ( ‘ 请输入一个用户名: )

//提示输入用户名,赋给变量 username

for name in names:  //遍历列表中的每个元素

if username == name      //如果输入的值存在

print(‘用户名已经存在’)  //提示已存在

break            //退出循环

else:            //循环结束之后,如果都不存在

names.append(username)

/则把当前输入的 username 元素加入列表中

print(names)  //输出查看最后列表中含有的元素

else for 对齐,会等待循环结束,输入的元素被一一与列表中元素判断后,再选择是否加入元素。如输入 lisi,会提示用户已经存在,而输入 jack 则会将其加入到列表中。

输出[ ' zhangsan ' , ' lisi ' , ' chris ' , ' jerry ' , 'henry ' ,'jack']


二、冒泡排序优化

首先定义一组列表数据,现要对数据进行排序,根据冒泡排序的核心思想,将当前数不断和下一个数进行比较。

我们写一个 while 循环,循环次数为 len(nums)-1,因为在比较中我们最多可以取到倒数第二个数进行比较,因为最后一个数没有下一个数可以比较。再使用 if nums [i] > nums [i+1] 判断前一个数和后一个数之间的大小,

如果前一个数大于后一个数,交换两者位置。到此就完成了一次循环。但我们需要比较多趟,所以再添加一个循环。循环次数为同为 en(nums) - 1。到此输出结果就变为有序。

代码

#冒泡完善

nums = [6,5,3,1,8,7,2,4]

j= 0

while i < len(nums) - 1:

j += 1

i = 0

while n <len(nums) - 1:

//如果前一个数据大于后一个数据

count += 1

if nums [i] > nums [i+1]

//交换位置

nums[i]nums[i + 1] = nums[i + 1] , nums[i]

i += 1

print(nums) //输出排序后的列表

print(‘比较了%d次’ % count)//比较次数,复杂度为o(n-1)的平方

输出结果

[12345678]

比较了49

至此共比较了49次,因为列表共有8个数,每趟比较7次,共比较7趟,所以为7*7=49次。复杂度为 o(n-1)的平方,如n=8,则49次。其中也有许多重复比较的过程。

1.png

1.优化每一趟比较次数

如在第一趟中,是每个元素都互相比较,比较8次。

1.png

但在第二趟比较时,531比较时交换,但在与67比不交换。

74比时交换,但最后78其实并没有比较的意义。因为冒泡排序每一趟都是找到一个最大数,第一趟就已经找到了最大数8在末尾。所以我们可以将其删减优化。

1.png

1.png

依次类推在第三趟时,最后678都无需比较。

1.png

总结:每次多比较的次数就是j的值。

#第一趟比较时,j=0,多比较了0

#第二趟比较时,j=1,多比较了1

#第三趟比较时,j=2,多比较了2

代码

nums = [6,5,3,1,8,7,2,4]

count = 0

j= 0

#第一趟比较时,j=0,多比较了0

#第二趟比较时,j=1,多比较了1

#第三趟比较时,j=2,多比较了2

while i < len(nums) - 1:

i = 0

while n <len(nums) - 1-j:  //在每次比较时减去多余的次数j

count += 1

if nums [] > nums [i+1]

nums[i]nums[i + 1] = nums[i + 1] , nums[i]

i += 1

//要将 j+=1写在末尾,否则初始值就变为了1,在减次数时就会多减

j += 1

print(nums)

print(‘比较了%d’ %count)

输出结果

[12345678]

比较了28

代码中j为比较的趟数,i为比较的次数,所以要减少每趟多余比较的次数,只需要将次数变为<len(nums) -1 -j,同时将j+=1放在最后即可;此时第一次比较就会变为7趟,第二次比较就会变为6趟,依次递减。优化之后复杂度变为2/n(n-1),总比较次数变为28次。

2.优化总比较趟数

但在第六趟的比较过程中,列表的值已变为有序的。但仍在重复进行比较。同理此后的第七次根本没有必要执行。

1.png

所以我们可以对总比较趟数进行优化,在每一趟之后定义一个 flag,设置其初始值为 True 假设每一趟都没有换行,同时在一趟比较之后,falg 依然为 True,说明本趟没有进行数据的交换,那么就执行 break 退出循环。

最后优化结果变为比较27次,因为当第六趟发现数据不在进行交换时,就退出了循环。最后的第七趟没有再比较。

代码

nums = [6,5,3,1,8,7,2,4]

count = 0

j= 0

#第一趟比较时,j=0,多比较了0

#第二趟比较时,j=1,多比较了1

#第三趟比较时,j=2,多比较了2

while i < len(nums) - 1:

#在每一趟里都定义一个 flag

flag=True #假设每一趟都没有换行

i = 0

while n <len(nums) - 1-j:

count += 1

if nums [i] > nums [i+1]

#只要交换了,说明 flag 不对为 false

falg=False

nums[i]nums[i + 1] = nums[i + 1] , nums[i]

i += 1

if flag:

#这一趟走完,flag 依然是 Ture,说明这一趟没有进行过数据交换

break//停止循环

j += 1  //进行下一趟

print(nums)

print(‘比较了%d’ %count)

输出结果

[12345678]

比较了27

总结

设立一个 flag=Ture,当发现本趟未执行数据交换时,就不会执行 if nums [i] > nums [i+1]flag 不变为 false,执行 if flag:

后的 break 退出循环。

2.  一键替换变量名

Tip:一键替换代码中的 flag 变量名,直接双击 flag,右键找到 Refactor Rename 重命名将其改为要更换的变量名 a 即可。

1.png

4.优化效果

在列表数据为[6,5,3,1,8,7,2,4]这样乱序时优化并不明显。但是当列表的数据几乎排序好时,如[1,2,3,4,5,6,7,9,8],在未优化时仍需要64次,但加上优化每一趟比较次数之后仅需要36,而优化总比较趟数之后就变为15次。


相关文章
|
存储 Python
Python代码搞定分数等级划分
Python代码搞定分数等级划分
979 0
|
4月前
|
SQL 人工智能 数据库
【三桥君】如何正确使用SQL查询语句:避免常见错误?
三桥君解析了SQL查询中的常见错误和正确用法。AI产品专家三桥君通过三个典型案例:1)属性重复比较错误,应使用IN而非AND;2)WHERE子句中非法使用聚合函数的错误,应改用HAVING;3)正确的分组查询示例。三桥君还介绍了学生、课程和选课三个关系模式,并分析了SQL查询中的属性比较、聚合函数使用和分组查询等关键概念。最后通过实战练习帮助读者巩固知识,强调掌握这些技巧对提升数据库查询效率的重要性。
164 0
|
编解码 网络协议
如何轻松地 rip 3D Blu-ray:详细步骤指南
随着3D电影和家庭影院的普及,越来越多的人希望将3D Blu-ray电影转换为数字文件,以便在多种设备上播放。本文介绍了使用DVDFab、MakeMKV+HandBrake和Leawo Blu-ray Ripper等软件轻松rip 3D Blu-ray的方法,帮助用户享受高质量的3D观影体验。这些工具不仅提供了便捷性和高质量的输出,还能节省存储空间。
852 9
|
6月前
|
安全 Java API
银行转账p图在线生成, 虚拟转账生成器, 银行卡转账模拟器【娱乐装逼神器】
这是一套模拟银行核心业务逻辑的Java程序,包含账户管理、资金存取与转账、交易记录等功能。代码采用线程安全设计
|
6月前
|
C++
爱心代码 C++
这段C++代码使用EasyX图形库生成动态爱心图案。程序通过数学公式绘制爱心形状,并以帧动画形式呈现渐变效果。运行时需安装EasyX库,教程链接:http://【EasyX图形库的安装和使用】https://www.bilibili.com/video/BV1Xv4y1p7z1。代码中定义了屏幕尺寸、颜色数组等参数,利用随机数与数学函数生成动态点位,模拟爱心扩散与收缩动画,最终实现流畅的视觉效果。
935 0
|
程序员 调度 开发工具
DOS系统
【10月更文挑战第15天】DOS系统
696 3
|
运维 搜索推荐 数据安全/隐私保护
阿里云实时计算Flink版测评报告
阿里云实时计算Flink版在用户行为分析与标签画像场景中表现出色,通过实时处理电商平台用户行为数据,生成用户兴趣偏好和标签,提升推荐系统效率。该服务具备高稳定性、低延迟、高吞吐量,支持按需计费,显著降低运维成本,提高开发效率。
311 1
|
机器学习/深度学习 人工智能 搜索推荐
AI与未来医疗:重塑健康的双刃剑
【10月更文挑战第6天】 人工智能作为现代科技的巅峰之作,已经渗透进我们生活的方方面面。从语音助手到自动驾驶,AI不仅改变了我们的日常,更在各个专业领域,特别是医疗行业,扮演着愈发重要的角色。本文探讨了AI在未来医疗中的应用及其潜在影响,揭示了这把“双刃剑”的机遇与挑战。
428 1
|
Web App开发 JSON 前端开发
我理解的测试开发与实践总结——新人篇
本文以作者的视角,讲述了测试与开发、产品之间的关系,如何做好一个测试以及做好一个测试应当具有的素质与技能。
|
编解码 JavaScript 前端开发
【专栏】介绍了字符串Base64编解码的基本原理和在Java、Python、C++、JavaScript及Go等编程语言中的实现示例
【4月更文挑战第29天】本文介绍了字符串Base64编解码的基本原理和在Java、Python、C++、JavaScript及Go等编程语言中的实现示例。Base64编码将24位二进制数据转换为32位可打印字符,用“=”作填充。文中展示了各语言的编码解码代码,帮助开发者理解并应用于实际项目。
598 1