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 web项目中资源国际化
有一些网站会有语言栏选项: 选择英文,内容就显示为英文: 选择中文,内容就显示文中文. 这里就用到了国际化资源. 先看效果图: 步骤: 1.建立资源包: mess_en_US.properties ( ...
- iReport5.6.0使用说明
1,需要安装jdk1.7,因为目前还不支持最新的jdk1.8 2,安装好软件之后,打开安装目录下的etc/ireport.conf文件,配置关联自己的jdk1.7的路径,如下: #jdkhome=&q ...
- [转]Adobe CC 2018 下载链接 Creative Cloud 2018 - Creative Cloud 2018 – Adobe CC 2018 Download Links
Creative Cloud 2018 – Adobe CC 2018 Download Links – ALL Languages Adobe CC 2018Direct Downloads Win ...
- bat脚本启动exe并打开文件后退出 + 中文乱码
写了个脚本用于复制模板到新的cpp文件. 将脚本路径加到环境变量里,只需在cmd窗口输入“new hdu 1419”,就会自动将模板拷贝到WORK_DIR下的hdu文件夹内一个名叫"1419 ...
- 此请求的查询字符串的长度超过配置的 maxQueryStringLength 值
异常详细信息: System.Web.HttpException: 此请求的查询字符串的长度超过配置的maxQueryStringLength 值. 我碰到此问题出现的原因是重写了HttpModule ...
- double int 类型的区别
内部组织格式不同: po [NSString stringWithFormat:@"%d", f] 107886912 (lldb) po [NSString stringWith ...
- ActiveMQ学习笔记(10)----ActiveMQ容错的连接
1. Failover Protocol 前面讲述的都是Client配置连接到指定的broker上,但是,如果Broker的连接失败怎么办呢?此时,Client有两个选项:要么立刻死掉,要么连接到其他 ...
- 路飞学城Python-Day10
[37.函数-命名空间]命名空间又称为name space,顾名思义就是存放名字的地方,存什么名字呢?举例说明,若变量 x = 1,存放于内存中,那名字x存放在哪里呢?名称空间正式存放名字x和1绑定关 ...
- 利用fabric批量安装kvm虚拟机及其xp
公司一批PC机需要安装多个虚拟机跑任务,搞来搞去决定用centos7安装KVM来跑.于是先折腾了一下午,利用早先搭建好的cobbler给PC机安装OS.然后fabric批量部署. 环境:centos7 ...
- CSS核心原理
1.优先原则: 后解析的内容,会覆盖掉之前解析的内容: 同一个选择器:文件执行从上往下,后面的样式会覆盖前面的: 如下例中color最终为粉色: div { color:red; color:pink ...