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.冒泡排序:两两比较,互换位置 ...
随机推荐
- Linux部署之批量自动安装系统之NFS篇
1. 编辑配置文件让远端设备可访问vim /etc/exports 2. 启动服务
- hiho1116 - 数据结构 线段树(区间合并)
题目链接 现在有一个有n个元素的数组a1, a2, ..., an. 记f(i, j) = ai * ai+1 * ... * aj. 初始时,a1 = a2 = ... = an = 0,每次我会修 ...
- 路飞学城Python-Day13
[2.常用模块-模块的种类和导入方法] 1.什么是模块? 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长.越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分 ...
- django 获得请求头
django 获得到的请求头封装在 request 的 META 中,为一个 dict 以下选自官方文档: https://docs.djangoproject.com/zh-hans/2.0/ref ...
- 前端那些事之----jQuery
1.jquery是什么 一个js的框架,可以方便的使用js 2 什么是jQuery对象 是由jQuery封装后的DOM对象 注意:与DOM对象的方法不同,不可以混用,但是可以相 ...
- python 面向对象 继承
什么是继承 继承表达的是一种”是“的关系,比如人是动物 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类 继承是基于抽象的结 ...
- 【转】Geometry cannot have Z values
http://blog.csdn.net/tweeenty/article/details/44246407 在对矢量要素类添加要素,进行赋几何信息时(FeatureBuffer.Shape = IG ...
- Qt之自定义布局管理器(QBorderLayout)
简述 QBorderLayout,顾名思义-边框布局,实现了排列子控件包围中央区域的布局. 具体实现要求不再赘述,请参考前几节内容. 简述 实现 效果 源码 使用 实现 QBorderLayout主要 ...
- cocos2dx 使用spine制作骨骼动画
刚刚接触骨骼动画,所以写一篇文章记录. 1.首先先画好人物的每一个部件: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fon ...
- js时间格式化函数,支持Unix时间戳
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...