python-排序算法 冒泡和快速排序
交换排序
交换排序有冒泡排序和快速排序
冒泡排序
冒泡排序就是每次找出最大(最小)元素,放在集合最前或最后,这是最简单的排序算法
print("未排序之前:",collection)#不能写成+(会提示为不是str类型数据,要写成这样) #升序排列 temp=collection[0] length=len(collection) for s in range(length-1): for i in range(length-1-s): if collection[i]>collection[i+1]:#前者大需要换位置,并需要判断他是否是最大的 temp=collection[i] collection[i]=collection[i+1] collection[i+1]=temp else: continue print("排序第",s+1,"轮之后:",collection)#print()好占时间啊
快速排序
快速排序是对冒泡排序的一种改进,冒泡排序作为一种广为人知的最简单的排序算法,存在着很多不足,比如他每趟遍历后只能从当前数列中挑出一个最大(最小)的数值,然后下趟工作再挑出剩下中的最大元素。这样看来,每趟之间几乎是完全独立的,这一趟的排序除了能使带排序的元素减少一个之外,并不会留下任何信息。这很明显就浪费了这一趟又一趟的比较。完全可以从一趟一趟中了解关于带排序的样本的更多信息。
快速排序就是另外一种思路,他最明显的特点就是“分而治之”。快速排序首先会选择两个游标,游标是移动的,在初始化的时候,我们一般将数组元素的第一个和最后一个元素(注意,代表的数组地址,会移动),然后他们两个交替的向前或者向后移动,每次移动一个元素,然后与一个值比较,(并不会让他们两个相互比较,)我们习惯上将这个值称为key,这个值初始化为数组首元素。
在比较的过程中,由于两个游标(一个i,一个j)是交替移动的,所以他们必然有相遇的时候,我将每次相遇,看作为一轮比较的结束,这一轮会将待排序的数组分为3个部分,一个部分只有key,另外两个部分分别存放比key小和比key大的元素。这就是分而治之的结果,除了只有一个元素的结果,下一次的分治过程又会从他们里面开始。
每一轮中的比较结果首先从i或j与key的比较开始,是i还是j怎样都行。我只需要记住,比较是为了将结果向有序的升序(或者降序)去靠拢。每一轮都是为了减小颗粒度。拿升序来说,如果i代表的下标所指的数组元素比key小(因为key代表数组首元素),那么他就应该和key交换,如果没有就向后移动一次,然后换j与key比较。
我的问题
1)当所有分而治之的结果 的左边都被排序好了,或者颗粒度是最小的,那么右边的就不排了。换句话说,剩下的所有工作都不去做了。
(sort) λ python bubble_sort.py 未排序之前: [70, 78, 85, 10, 66, 43, 89, 62, 11, 41] key两边的数组是: [41] [ 70 ] [85, 10, 66, 43, 89, 62, 11, 78] *************************i,j的值分别为 1 9 key两边的数组是: [41, 11] [ 70 ] [10, 66, 43, 89, 62, 85, 78] *************************i,j的值分别为 2 8 key两边的数组是: [41, 11, 62, 10, 66, 43] [ 70 ] [89, 85, 78] *************************i,j的值分别为 6 7 key两边的数组是: [41, 11, 62, 10, 66, 43] [ 70 ] [89, 85, 78] *************************i,j的值分别为 6 6 key两边的数组是: [10, 11] [ 41 ] [62, 66, 43] *************************i,j的值分别为 2 3 key两边的数组是: [10, 11] [ 41 ] [62, 66, 43] *************************i,j的值分别为 2 2 key两边的数组是: [] [ 10 ] [11] *************************i,j的值分别为 0 0 key两边的数组是: [] [ 41 ] [62, 66, 43] *************************i,j的值分别为 0 0 key两边的数组是: [] [ 70 ] [89, 85, 78] *************************i,j的值分别为 0 0 排序之后: [41, 11, 62, 10, 66, 43, 70, 89, 85, 78] 耗费时间: 0.023987293243408203
2)为什么第二趟都从0开始啊
解决办法:这个不是程序的原因,而是因为程序递归到第二次时,穿过去的数组中指定的key就是最小的了。
未排序之前: [6, 5, 4, 8, 7, 9, 3, 2, 1] *************************又经过了一次j交换,交换的数组下标j的值为 8 这时的数组为 [1, 5, 4, 8, 7, 9, 3, 2, 6] *************************又经过了一次i交换,交换的数组下标i的值为 3 这时的数组为 [1, 5, 4, 6, 7, 9, 3, 2, 8] *************************又经过了一次j交换,交换的数组下标j的值为 7 这时的数组为 [1, 5, 4, 2, 7, 9, 3, 6, 8] *************************又经过了一次i交换,交换的数组下标i的值为 4 这时的数组为 [1, 5, 4, 2, 6, 9, 3, 7, 8] *************************又经过了一次j交换,交换的数组下标j的值为 6 这时的数组为 [1, 5, 4, 2, 3, 9, 6, 7, 8] *************************又经过了一次i交换,交换的数组下标i的值为 5 这时的数组为 [1, 5, 4, 2, 3, 6, 9, 7, 8] *************************又经过了一次j交换,交换的数组下标j的值为 5 这时的数组为 [1, 5, 4, 2, 3, 6, 9, 7, 8] *************************又经过了一次i交换,交换的数组下标i的值为 5 这时的数组为 [1, 5, 4, 2, 3, 6, 9, 7, 8] 这一轮过后key两边的数组是: [1, 5, 4, 2, 3] [ 6 ] [9, 7, 8] *************************又经过了一次j交换,交换的数组下标j的值为 0 这时的数组为 [1, 5, 4, 2, 3] *************************又经过了一次i交换,交换的数组下标i的值为 0 这时的数组为 [1, 5, 4, 2, 3] 这一轮过后key两边的数组是: [] [ 1 ] [5, 4, 2, 3] *************************又经过了一次j交换,交换的数组下标j的值为 0 这时的数组为 [6, 9, 7, 8] *************************又经过了一次i交换,交换的数组下标i的值为 0 这时的数组为 [6, 9, 7, 8] 这一轮过后key两边的数组是: [] [ 6 ] [9, 7, 8] 排序之后: [1, 5, 4, 2, 3, 6, 9, 7, 8] L: [1, 5, 4, 2, 3, 6, 9, 7, 8]
第一次版本,失败了
def quick_sort(collection): length=len(collection) i=0 j=length-1 if(length>1): key=collection[0] print("新一轮的排序开始了i,j,key的值分别为",i,j,key,"被排序的数组是:",collection,'此次被排序数组的长度是:',length) while(i<j): while(collection[j]>key): j=j-1 collection[i],collection[j]=collection[j],collection[i] print('*'*25+'又经过了一次j交换,交换的数组下标j的值为',j,'这时的数组为',collection) while(collection[i]<key): if(i<j): i=i+1 break collection[i],collection[j]=collection[j],collection[i] print('*'*25+'又经过了一次i交换,交换的数组下标i的值为',i,'这时的数组为',collection) print("这一轮过后key两边的数组是:"+' '*53,collection[0:i],'[',key,']',collection[i+1:length],'整个数组为:',collection,'\n')#要加逗号啦 # L.extend(collection) #递归 if(i>0): # print('现在的L是:',L) print('对%s的左边排序'%(key)) print('%s左边返回的结果是'%(key),quick_sort(collection[0:i]),'key是',key) # s=quick_sort(collection[0:i]) # if(s!=-1): # L.extend(s) # L.append(key) # print("s是:",s,'key是',key) if(j>0):#为什么这里不能写成elif类,因为这两个判断应该是相互独立的,即在分而治之的过程中,i代表的左边 #没有元素了,然后在处理右边,如果改成elif,那么情况就会变成如果i<0了,那么就会不管右边了,即判断 #右边需不需要处理的判断就会只有满足了第一个条件之后才会进入。 # print('右边返回的结果是',quick_sort(collection[j+1:length])) print('对%s的右边进行排序'%(key)) print('%s右边返回的结果是'%(key),quick_sort(collection[j+1:length])) # s=quick_sort(collection[j+1:length]) # if(s!=-1): # L.extend(s) # print("s是:",s) # print('现在的L是:',L) # print("此轮被排序的数组长度为1") elif(length>0): return collection#忽略了一点,原以为这里即使不写else return也会只有在数组长度等于1的长度下被返回的,即返回单个数,但实际情况可能不是这样的。 print('这里已经没有元素了') return -1 #产生排序数组 # collection=random.sample(range(1,100),10) # collection =[6,5,4,8,7,9,3,1,2] collection= [94, 37, 97, 31, 26, 79, 10, 35, 40, 6] startTime=time.time() print("未排序之前:"+' '*68,collection)#不能写成+(会提示为不是str类型数据,要写成这样) print("排序之后:",quick_sort(collection),'L:',L) endTime=time.time() print("耗费时间:",endTime-startTime)
失败的原因是:
未排序之前: [94, 37, 97, 31, 26, 79, 10, 35, 40, 6] 新一轮的排序开始了i,j,key的值分别为 0 9 94 被排序的数组是: [94, 37, 97, 31, 26, 79, 10, 35, 40, 6] 此次被排序数组的长度是: 10 *************************又经过了一次j交换,交换的数组下标j的值为 9 这时的数组为 [6, 37, 97, 31, 26, 79, 10, 35, 40, 94] *************************又经过了一次i交换,交换的数组下标i的值为 1 这时的数组为 [6, 94, 97, 31, 26, 79, 10, 35, 40, 37] *************************又经过了一次j交换,交换的数组下标j的值为 9 这时的数组为 [6, 37, 97, 31, 26, 79, 10, 35, 40, 94] *************************又经过了一次i交换,交换的数组下标i的值为 2 这时的数组为 [6, 37, 94, 31, 26, 79, 10, 35, 40, 97] *************************又经过了一次j交换,交换的数组下标j的值为 8 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35, 94, 97] *************************又经过了一次i交换,交换的数组下标i的值为 3 这时的数组为 [6, 37, 40, 94, 26, 79, 10, 35, 31, 97] *************************又经过了一次j交换,交换的数组下标j的值为 8 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35, 94, 97] *************************又经过了一次i交换,交换的数组下标i的值为 4 这时的数组为 [6, 37, 40, 31, 94, 79, 10, 35, 26, 97] *************************又经过了一次j交换,交换的数组下标j的值为 8 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35, 94, 97] *************************又经过了一次i交换,交换的数组下标i的值为 5 这时的数组为 [6, 37, 40, 31, 26, 94, 10, 35, 79, 97] *************************又经过了一次j交换,交换的数组下标j的值为 8 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35, 94, 97] *************************又经过了一次i交换,交换的数组下标i的值为 6 这时的数组为 [6, 37, 40, 31, 26, 79, 94, 35, 10, 97] *************************又经过了一次j交换,交换的数组下标j的值为 8 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35, 94, 97] *************************又经过了一次i交换,交换的数组下标i的值为 7 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 94, 35, 97] *************************又经过了一次j交换,交换的数组下标j的值为 8 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35, 94, 97] *************************又经过了一次i交换,交换的数组下标i的值为 8 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35, 94, 97] 这一轮过后key两边的数组是: [6, 37, 40, 31, 26, 79, 10, 35] [ 94 ] [97] 整个数组为: [6, 37, 40, 31, 26, 79, 10, 35, 94, 97] 对94的左边排序 新一轮的排序开始了i,j,key的值分别为 0 7 6 被排序的数组是: [6, 37, 40, 31, 26, 79, 10, 35] 此次被排序数组的长度是: 8 *************************又经过了一次j交换,交换的数组下标j的值为 0 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35] *************************又经过了一次i交换,交换的数组下标i的值为 0 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35] 这一轮过后key两边的数组是: [] [ 6 ] [37, 40, 31, 26, 79, 10, 35] 整个数组为: [6, 37, 40, 31, 26, 79, 10, 35]#这里该向下递归的没有递归 这里已经没有元素了 94左边返回的结果是 -1 key是 94 对94的右边进行排序 94右边返回的结果是 [97] 这里已经没有元素了 排序之后: -1 L: [] 耗费时间: 0.008994817733764648
我猜想可能是因为对左边或右边进行排序的时候没有响应的判断逻辑。
3)修正
while(i<j):#这里不应该是i<j-1,即使这样能避免有些交换数组下标的重复,但会产生下面的问题,当排序三个元素的数组中key为中间值时,会忽略右边的元素。 print('先输出i=%s j=%s'%(i,j)) while(collection[j]>key): j=j-1 collection[i],collection[j]=collection[j],collection[i] print('*'*25+'又经过了一次j交换,交换的数组下标j的值为',j,'这时的数组为',collection) while(collection[i]<key): i=i+1 collection[i],collection[j]=collection[j],collection[i]#正是这一句导致了重复定位ij的结果,因为即使上面的while #起了作用,这句也会运行的。 print('*'*25+'又经过了一次i交换,交换的数组下标i的值为',i,'这时的数组为',collection) 新一轮的排序开始了i,j,key的值分别为 0 2 4 被排序的数组是: [4, 5, 3] 此次被排序数组的长度是: 3 先输出i=0 j=2 *************************又经过了一次j交换,交换的数组下标j的值为 2 这时的数组为 [3, 5, 4] *************************又经过了一次i交换,交换的数组下标i的值为 1 这时的数组为 [3, 4, 5] 先输出i=1 j=2 *************************又经过了一次j交换,交换的数组下标j的值为 1 这时的数组为 [3, 4, 5] *************************又经过了一次i交换,交换的数组下标i的值为 1 这时的数组为 [3, 4, 5] 这一轮过后key两边的数组是: [3] [ 4 ] [5] 整个数组为: [3, 4, 5] 对4的左边排序 4左边返回的结果是 [3] key是 4 对4的右边进行排序 4右边返回的结果是 [5] 这里已经没有元素了 2右边返回的结果是 -1 这里已经没有元素了 6左边返回的结果是 -1 key是 6 对6的右边进行排序
python-排序算法 冒泡和快速排序的更多相关文章
- python排序算法-冒泡和快速排序,解答阿里面试题
''常见的排序算法\ 插入排序/希尔排序/直接排序/堆排序 冒泡排序/快速排序/归序排序/基数排序 给定一个列表,将这个列表进行排序,要求:> 时间复杂度要小于O(n^2) 复杂度:1.时间复杂 ...
- js实现两种实用的排序算法——冒泡、快速排序
分类:js (4443) (0) 零:数据准备,给定数组arr=[2,5,4,1,7,3,8,6,9,0]; 一:冒牌排序 1思想:冒泡排序思想:每一次对比相邻两个数据的大小,小的排在前面,如果前 ...
- js实现两种排序算法——冒泡、快速排序
* 一:冒牌排序1思想:冒泡排序思想:每一次对比相邻两个数据的大小,小的排在前面,如果前面的数据比后面的大就交换这两个数的位置要实现上述规则需要用到两层for循环,外层从第一个数到倒数第二个数,内层从 ...
- Python排序算法——快速排序
有趣的事,Python永远不会缺席! 如需转发,请注明出处:小婷儿的python https://www.cnblogs.com/xxtalhr/p/10768593.html 排序算法(Sortin ...
- python排序算法实现(冒泡、选择、插入)
python排序算法实现(冒泡.选择.插入) python 从小到大排序 1.冒泡排序: O(n2) s=[3,4,2,5,1,9] #count = 0 for i in range(len(s)) ...
- 44.python排序算法(冒泡+选择)
一,冒泡排序: 是一种简单的排序算法.它重复地遍历要排序的数列,一次比较两个,如果他们的排序错误就把他们交换过来. 冒泡排序是稳定的(所谓稳定性就是两个相同的元素不会交换位置) 冒泡排序算法的运作如下 ...
- python 排序算法总结及实例详解
python 排序算法总结及实例详解 这篇文章主要介绍了python排序算法总结及实例详解的相关资料,需要的朋友可以参考下 总结了一下常见集中排序的算法 排序算法总结及实例详解"> 归 ...
- 带你掌握4种Python 排序算法
摘要:在编程里,排序是一个重要算法,它可以帮助我们更快.更容易地定位数据.在这篇文章中,我们将使用排序算法分类器对我们的数组进行排序,了解它们是如何工作的. 本文分享自华为云社区<Python ...
- Python排序算法之选择排序定义与用法示例
Python排序算法之选择排序定义与用法示例 这篇文章主要介绍了Python排序算法之选择排序定义与用法,简单描述了选择排序的功能.原理,并结合实例形式分析了Python定义与使用选择排序的相关操作技 ...
- python排序算法之冒泡,选择,插入
1.参考 一本关于排序算法的 GitBook 在线书籍 <十大经典排序算法>,使用 JavaScript & Python & Go 实现 2.冒泡排序:两两比较,互换位置 ...
随机推荐
- java的可查的异常和不可查的异常讲解
java的可查的异常和不可查的异常讲解: Java的异常(包括Exception和Error)分为:可查的异常(checked exceptions)和不可查的异常(unchecked excepti ...
- stm8s103 EEPROM烧程序时能否保留
EEPROM的参数需要再烧录程序时保留,做试验测试是否能够保留 1.在ST Visual Develop中硬件仿真手动修改EEPROM的值. 2.在ST Visual Programmer中读取EEP ...
- windows2008 虚拟机64位的操作系统安装32位的应用程序
64位的操作系统安装32位的应用程序: 安装成功但是使用有问题 报错: 最终解决: 在一台物理机的win7上面安装该软件. 然后把安装好的文件全部拷贝到win2008虚拟机上面 启动,使用 多ok了! ...
- swift学习笔记 - swift中常用关键字
swift中常用关键字 **用作声明的关键字: ** class.deinit.enum.extension.func.import.init.let.protocol.static.struct.s ...
- MySQL 数据还原
1.1还原使用mysqldump命令备份的数据库的语法如下: mysql -u root -p [dbname] < backup.sq 示例: mysql -u root -p < C: ...
- python基础7(函数 Ⅱ)
1.python代码运行遇到函数时 从python解释器开始执行之后,就在内存中开辟了一个空间 每当遇到一个变量的时候,就把变量名和值之间的对应关系记录下来. 但是当遇到函数定义的时候解释器只是象征性 ...
- GenIcam标准(三)
2.6. 缓存 如果某个实现对每个写操作支持范围.实现和可用状态的检查,通常会触发一系列对相机的读操作.大多数用于有效性检查的数值很少或不会发生变化,所以可以放入缓存.相机描述文件包含所有必需的定义以 ...
- C/C++中相对路径与绝对路径以及斜杠与反斜杠的区别
1 绝对路径与相对路径 绝对路径表示相对容易得多,依次将文件所在盘符文件夹逐级展开就是绝对路径: ofstream infile("E:\\MyDoc\\file.txt", io ...
- 【转】C#正则表达式教程和示例
[转]C#正则表达式教程和示例 有一段时间,正则表达式学习很火热很潮流,当时在CSDN一天就能看到好几个正则表达式的帖子,那段时间借助论坛以及Wrox Press出版的<C#字符串和正则表达式参 ...
- 和同事合作开发,使用局域网 git创建本地仓库
转自原文 和同事合作开发,使用局域网 git创建本地仓库 1.仓库 建一个空文件夹来做仓库,例如建为 cangku 1.1 cd 到 cangku目录下 创建远程仓库容器 mkdir mycangk ...