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.冒泡排序:两两比较,互换位置 ...
随机推荐
- Maven远程仓库:pom依赖以及jar包下载
Maven远程仓库:pom依赖xml配置以及jar包下载: 地址1: http://mvnrepository.com/ 地址2: http://172.16.163.52:8081/nexus/#w ...
- XManager远程Linux 安装Oracle 图形化界面xstart解决方法
一.安装Oracle_11g_R21.安装所必要的软件包:(CentOS)参见官方文档-rw-r--r--. 1 oracle oinstall 1358454646 Feb 5 22:57 p10 ...
- Linux 安装软件的几种方式
目录 几种安装方式 源代码编译安装 借助软件包管理器安装 二进制格式安装 总结 参考 几种安装方式 源代码编译安装 源代码包的安装一般为下载软件源代码,然后编译安装.常见的 C 程序软件的安装步骤是 ...
- SLAM概念学习之随机SLAM算法
这一节,在熟悉了Featue maps相关概念之后,我们将开始学习基于EKF的特征图SLAM算法. 1. 机器人,图和增强的状态向量 随机SLAM算法一般存储机器人位姿和图中的地标在单个状态向量中,然 ...
- pthread_join/pthread_exit的用法解析
官方说法: 函数pthread_join用来等待一个线程的结束.函数原型为: extern int pthread_join __P ((pthread_t __th, void **__thread ...
- Js jquery常用的身份证号码 邮箱电话等验证
刷了很多博客,https://www.cnblogs.com/hao-1234-1234/p/6636843.html 只有这个比较靠谱.
- vue项目,封装api并使用
封装api index.js let uploadBase = '' if(process.env.NODE_ENV === 'production'){ uploadBase = 'https:// ...
- 题解 P2532 【[AHOI2012]树屋阶梯】
本题运用卡特兰数求解. 卡特兰数有两种表达方式: 1)\(h_i=\sum^{k=0}_{i-1}h_kh_{i-k-1}\) 2)\(h_i=\frac{1}{n+1}C^{n}_{2n}\) 运用 ...
- NYIST 1108 最低的惩罚
最低的惩罚 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 那么现在问题就来了... 给你N(1=<N<=15)个任务,每个任务有一个截止完成时间t(1= ...
- hadoop-14-进行libtirpc的rpm包安装
hadoop-14-进行libtirpc的rpm包安装 安装过程中出现了这个问题,进行安装: yum localinstall --nogpgcheck libtirpc-0.2.1-13.el6.x ...