python输入十个数用冒泡排序_利用python 实现10个排序算法_weixin_39664136的博客-程序员秘密

技术标签: python输入十个数用冒泡排序  

需要的库:

import sys

import time

sys.setrecursionlimit(1000000) #手动设置递归深度,如果不设置,当数字取多一些时,快速排序,归并函数因为利用了递归, 会溢出,报错

首先先建立一个函数得出1000个大小在(0,9999)之间的随机数

# 随机生成0-10000之间的数值

def getrandata(num):

a = []

i = 0

while i <= num:

a.append(random.randint(0, 9999))

i += 1

print(a)

return a

a = getrandata(1000)

1、冒泡排序

冒泡排序是最简单的排序之一了,其大体思想就是通过与相邻元素的比较和交换来把小的数交换到最前面。这个过程类似于水泡向上升一样,因此而得名。举个栗子,对5,3,8,6,4这个无序序列进行冒泡排序。首先从后向前冒泡,4和6比较,把4交换到前面,序列变成5,3,8,4,6。同理4和8交换,变成5,3,4,8,6,3和4无需交换。5和3交换,变成3,5,4,8,6,3.这样一次冒泡就完了,把最小的数3排到最前面了。对剩下的序列依次冒泡就会得到一个有序序列。冒泡排序的时间复杂度为O(n^2)。

# 冒泡排序 时间复杂度O(n^2)

'''

算法思路: 每次从最后开始往前面滚,相邻元素两两比较,小元素交换到前面,每一轮把最小到元素上浮至第一个位置

第一轮,n个数, 比较 n-1 次,得到最小数,放在第一位,

第二轮,比较剩余 n-1 个数, 比较 n-2 次, 得到第二小的数, 放在第二位

以此类推

最后总比较次数:1 + 2 + 3 + 。。。 + (n-1) = (1+n-1)*(n-1)/2 = n(n-1)/2

'''

def maopao(a):

start_time = time.time()*1000

x = len(a)

for i in range(x-1):

for j in range(i,x-1)[::-1]: # 每轮的比较数列为[第i个, 最后],因为每一轮已经将最小第数放到最前面

if a[j+1] < a[j]:

a[j], a[j+1] = a[j+1], a[j]

use_time = time.time()*1000 - start_time

print('1 冒泡排序: ',a,'\n', '使用时间: ', '%s ms' % use_time)

maopao(a)

结果:排序完的的结果太长,不列出来了, 使用时间: 155.197021484375 ms

2、插入排序

插入排序不是通过交换位置而是通过比较找到合适的位置插入元素来达到排序的目的的。相信大家都有过打扑克牌的经历,特别是牌数较大的。在分牌时可能要整理自己的牌,牌多的时候怎么整理呢?就是拿到一张牌,找到一个合适的位置插入。这个原理其实和插入排序是一样的。举个栗子,对5,3,8,6,4这个无序序列进行简单插入排序,首先假设第一个数的位置时正确的,想一下在拿到第一张牌的时候,没必要整理。然后3要插到5前面,把5后移一位,变成3,5,8,6,4.想一下整理牌的时候应该也是这样吧。然后8不用动,6插在8前面,8后移一位,4插在5前面,从5开始都向后移一位。注意在插入一个数的时候要保证这个数前面的数已经有序。简单插入排序的时间复杂度也是O(n^2)。

def insertSort(a):

start_time = time.time()*1000

for i in range(1, len(a)):

j = i

while j>0 and a[j-1] > a[i]:

j -= 1

a.insert(j,a[i])

a.pop(i+1)

use_time = time.time()*1000 - start_time

print('2 插入排序: ',a, '\n', '使用时间: ', '%s ms' % use_time)

insertSort(a)

使用时间: 52.470947265625 ms

3、快速排序

快速排序一听名字就觉得很高端,在实际应用当中快速排序确实也是表现最好的排序算 法。快速排序虽然高端,但其实其思想是来自冒泡排序,冒泡排序是通过相邻元素的比较和交换把最小的冒泡到最顶端,而快速排序是比较和交换小数和大数,这样一来不仅把小数冒泡到上面同时也把大数沉到下面。

# 快速排序 时间复杂度O(nlogn)

def quickSort(a):

start_time = time.time()*1000

def quick(a):

if len(a) <= 1:

return a

x = len(a)

i = 0

flag = a[i]

for j in range(1,x):

if a[j]< flag:

flag=a[j]

a.insert(0,flag)

a.pop(j+1)

i += 1

a1 = a[:i]

a2 = a[i+1:]

a = quick(a1)

a.append(flag)

a.extend(quick(a2))

return a

use_time = time.time()*1000 - start_time

print("3 快速排序: ", quick(a))

print(" 使用时间: %s ms" % use_time)

quickSort(a)

使用时间: 0.0009765625 ms

4、选择排序

选择排序的思想其实和冒泡排序有点类似,都是在一次排序后把最小的元素放到最前面。但是过程不同,冒泡排序是通过相邻的比较和交换。而选择排序是通过对整体的选择。举个栗子,对5,3,8,6,4这个无序序列进行简单选择排序,首先要选择5以外的最小数来和5交换,也就是选择3和5交换,一次排序后就变成了3,5,8,6,4.对剩下的序列一次进行选择和交换,最终就会得到一个有序序列。其实选择排序可以看成冒泡排序的优化,因为其目的相同,只是选择排序只有在确定了最小数的前提下才进行交换,大大减少了交换的次数。选择排序的时间复杂度为O(n^2)。

# 选择排序 时间复杂度O(n^2) 选择排序的思想其实和冒泡排序有点类似,都是在一次排序后把最小的元素放到最前面。

# 但是过程不同,冒泡排序是通过相邻的比较和交换。而选择排序是通过对整体的选择。

def selectSort(a):

start_time = time.time()*1000

x = len(a)

for i in range(x-1):

flag = a[i]

tmp = i

for j in range(i+1,x):

if flag > a[j]:

flag = a[j]

tmp = j

a[i],a[tmp] = a[tmp],a[i]

use_time = time.time()*1000 - start_time

print("4 选择排序: ", a, '\n', "使用时间: %s ms" % use_time)

# 时间复杂度也为 O(n^2)

selectSort(a)

使用时间: 40.88720703125 ms

5、希尔排序

# 希尔排序 如果待排序列是正序时,时间复杂度是O(n), 平均情况O(n^1.3)

# 希尔排序是插入排序的一种高效率的实现,也叫缩小增量排序。简单的插入排序中,如果待排序列是正序时,时间复杂度是O(n),

# 如果序列是基本有序的,使用直接插入排序效率就非常高。希尔排序就利用了这个特点。

# 基本思想是:先将整个待排记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录基本有序时再对全体记录进行一次直接插入排序(也可以其他方式)。

def shellSort(a):

start_time = time.time()*1000

x = len(a)

group = int(x/2)

while group > 0:

for i in range(group):

a1 = a[i::group]

for j in range(1,len(a1)):

k = j # 该位置数字 原始位置在 i+group*j

while k>0 and a1[k-1] > a1[j]:

k -= 1

a.insert(i+group*k,a1[j])

a.pop(i+group*j+1)

group = int(group/2)

use_time = time.time()*1000 - start_time

print("5 希尔排序: ", a, '\n', "使用时间: %s ms" % use_time)

shellSort(a)

使用时间: 11.671630859375 ms

6、计数排序

# 计数排序的时间复杂度和空间复杂度为O(n) 或时间复杂度O(n+k),空间复杂度为O(k) k为整数度范围

# 计数排序对输入的数据有附加的限制条件:

# 1、输入的线性表的元素属于有限偏序集S;

# 2、设输入的线性表的长度为n,|S|=k(表示集合S中元素的总数目为k),则k=O(n)。

# 在这两个条件下,计数排序的复杂性为O(n)。

def countSort(a):

start_time = time.time()*1000

b = [0 for i in range(10001)] #最小值最好为0 ,否则,算法需要改进, 如再建一个列表,利用list[-1]这样代表负数

for i in a:

b[i] += 1

a = []

for i in range(10000):

while b[i] >0:

a.append(i)

b[i] -= 1

use_time = time.time()*1000 - start_time

print("6 计数排序: ", a, "\n", "使用时间: %s ms" % use_time)

countSort(a)

使用时间: 1.761962890625 ms

7、桶排序

# 桶排序 总结:桶排序的平均时间复杂度为线性的O(N+C),其中C=N*(logN-logM)。如果相对于同样的N,桶数量M越大,其效率越高,

# 最好的时间复杂度达到O(N)。当然桶排序的空间复杂度为O(N+M),如果输入数据非常庞大,而桶的数量也非常多,则空间代价无疑是昂贵的。

# 此外,桶排序是稳定的。

'''

例如要对大小为[1..1000]范围内的n个整数A[1..n]排序,可以把桶设为大小为10的范围,具体而言,设集合B[1]存储[1..10]的整数,

集合B[2]存储(10..20]的整数,……集合B[i]存储((i-1)*10, i*10]的整数,i = 1,2,..100。总共有100个桶。然后对A[1..n]从头到尾扫描一遍,

把每个A[i]放入对应的桶B[j]中。 然后再对这100个桶中每个桶里的数字排序,这时可用冒泡,选择,乃至快排,一般来说任何排序法都可以。

最后依次输出每个桶里面的数字,且每个桶中的数字从小到大输出,这样就得到所有数字排好序的一个序列了。

'''

# 极限情况下一个数一个桶,这样就为计数排序,时间复杂度O(n)

# 以下为先分桶,再插入排序的方式,默认最大数为10000

def bucketSort(a,bucket_num):

start_time = time.time()*1000

sep = int(10000/bucket_num)+1

b = []

for i in range(1,bucket_num+1):

c = []

for j in a:

if j >= sep * (i-1) and j < i *sep:

c.append(j)

x = len(c)

for j in range(1,x):

k = j

while k >0 and c[k-1]>c[j]:

k -= 1

c.insert(k,c[j])

c.pop(j+1)

b.extend(c)

use_time = time.time()*1000 - start_time

print("7 桶排序 : ", b, "\n", "使用时间: %s ms" % use_time)

bucketSort(a,10)

使用时间: 6.691162109375 ms

8、归并排序

# 归并排序 时间复杂度为 O(nlogn)

# 将待排序序列R[0...n-1]看成是n个长度为1的有序序列,将相邻的有序表成对归并,得到n/2个长度为2的有序表;

# 将这些有序序列再次归并,得到n/4个长度为4的有序序列;如此反复进行下去,最后得到一个长度为n的有序序列。

def mergeSort(a):

start_time = time.time()*1000

def Sort(left, right):

left_right = []

while len(left) > 0 and len(right) > 0:

if left[0] < right[0]:

left_right.append(left[0])

left.pop(0)

else:

left_right.append(right[0])

right.pop(0)

if len(left) > 0:

left_right.extend(left)

else:

left_right.extend(right)

return left_right

def merge(a):

if len(a) <=1:

return a

x = int(len(a)/2)

left = merge(a[:x])

right = merge(a[x:])

return Sort(left, right)

a = merge(a)

use_time = time.time()*1000 - start_time

print("8 归并排序: ", a, "\n", "使用时间: %s ms" % use_time)

mergeSort(a)

使用时间: 7.035888671875 ms

9、基数排序

# 基数排序 基数排序是一种借助多关键字排序思想对单逻辑关键字进行排序的方法。

# 所谓的多关键字排序就是有多个优先级不同的关键字。比如说成绩的排序,如果两个人总分相同,则语文高的排在前面,语文成绩也相同则数学高的排在前面。。。

# 如果对数字进行排序,那么个位、十位、百位就是不同优先级的关键字,如果要进行升序排序,那么个位、十位、百位优先级一次增加。

# 基数排序是通过多次的收分配和收集来实现的,关键字优先级低的先进行分配和收集。

def radixSort(a,maxs):#为了速度,确定就不用max函数找出最大数多少位的,人工输入最大位数

start_time = time.time()*1000

for g in range(4):

x = [[] for i in range(10)]

for i in a:

radix = int(i/(10**g))%10

x[radix].append(i)

a = []

for i in x:

for j in i:

a.append(j)

use_time = time.time()*1000 - start_time

print("9 基数排序: ", a, "\n", "使用时间: %s ms" % use_time)

radixSort(a,4)

使用时间: 3.02294921875 ms

10、堆排序

# 堆排序与快速排序,归并排序一样都是时间复杂度为O(n*logn)的几种常见排序方法

# 按定义,堆中每次都只能删除第0个数据。为了便于重建堆,实际的操作是将最后一个数据的值赋给根结点,然后再从根结点开始进行一次从上向下的调整。

# 我选择将第一个元素重列表删除,那么第二个元素上升至第一个,再开始

# 调整时先在左右儿子结点中找最小的,如果父结点比这个最小的子结点还小说明不需要调整了,反之将父结点和它交换后再考虑后面的结点。

def heapSort(a):

start_time = time.time()*1000

b = []

x = len(a)

while x > 1:

for i in range(1,x)[::-1]:

j = int((i-1)/2)

if a[i] < a[j]:

a[i], a[j] = a[j], a[i]

b.append(a[0])

a.pop(0)

x -= 1

b.append(a[0])

use_time = time.time()*1000 - start_time

print("10 堆排序: ", b, "\n", "使用时间: %s ms" % use_time)

heapSort(a)

使用时间: 193.88818359375 ms

11、python的sorted函数

# 顺便测验一下python 自带的排序函数sorted的使用时间

def selfSort(a):

start_time = time.time() * 1000

a = sorted(a)

use_time = time.time() * 1000 - start_time

print("11 python的排序函数: ", a, "\n", "使用时间: %s ms" % use_time)

selfSort(a)

使用时间: 0.223876953125 ms

总结

冒泡排序、选择排序、插入排序三种简单的排序及其变种快速排序、堆排序、希尔排序三种比较高效的排序;

基于分治递归思想的归并排序还有计数排序、桶排序、基数排序三种线性排序;

可以知道排序算法要么简单有效,要么是利用简单排序的特点加以改进,要么是以空间换取时间在特定情况下的高效排序

参考:

http://www.imooc.com/article/8633

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_39664136/article/details/110274984

智能推荐

Paper:可解释性之VI/PFI《All Models are Wrong, but Many are Useful: Learning a Variable’s Importance》翻译与解读_可解释性 研究 paper_一个处女座的程序猿的博客-程序员秘密

Paper:《All Models are Wrong, but Many are Useful: Learning a Variable’s Importance by Studying an Entire Class of Prediction Models Simultaneously-所有模型都是错误的,但许多模型都是有用的:通过同时研究一整类预测模型来了解变量的重要性》翻译与解读目录《All Models are Wrong, but Many are Useful: Learning a Var

JDBC连接MySQL数据库Timezone时区问题FAQ_jdbc timezone_冰·河的博客-程序员秘密

JDBC连接MySQL数据库Timezone时区问题The server time zone value '?й???????' is unrecognized or represents more than one time zone.

利用Hellocharts绘制频谱瀑布图(雨图)_android狗儿的博客-程序员秘密

频谱瀑布图是众多频谱仪器上非常普遍的一种图,对于观察一段时间内信号的变化是非常突出的。因此在android上绘制2纬的瀑布图也是我们项目不可或缺的一部分。下面就一个小demo与大家分享。  经过多次对比,以及查看API文档,最终选择了hellocharts作为所依赖的图库,这个图库一直在github上更新。首先我将瀑布图设想为一层层的带有颜色的小块块向上堆叠的效果,而小块块颜色是与频谱

HDU-4609 3-idiots(FFT)_zhaozhengcc的博客-程序员秘密

给n条边,问随便取三个可以组成三角形的概率

python调用spark集群_干货分享:Python搭建Spark分布式集群环境_weixin_39600885的博客-程序员秘密

@本文来源于公众号:csdn2299,喜欢可以关注公众号 程序员学府这篇文章主要介绍了Spark分布式集群环境搭建基于Python版,Apache Spark 是一个新兴的大数据处理通用引擎,提供了分布式的内存抽象。100 倍本文而是使用三台电脑来搭建一个小型分布式集群环境安装,需要的朋友可以参考下前言Apache Spark 是一个新兴的大数据处理通用引擎,提供了分布式的内存抽象。Spark 最...

OpenCV 学习笔记-day16 正多边形绘制demo_opencv生成正n边形代码_追足梦幻的博客-程序员秘密

OpenCV 学习笔记day16 随机数与随机颜色day16 随机数与随机颜色给定边数n,中点坐标Point p;p.a(横坐标),p.b(纵坐标)和中点到顶点的距离d, 来绘制多边形首先确定多边形每一条边的旋转角度 angle,并转成弧度制,这个角度指的是中点到顶点连线与x轴的夹角double angle = 360.0 / n / 180.0PI;找到顶点坐标与旋转角度和中心点坐标的关系(注意第一次的旋转角度为0)for (int i = 0; i &lt; n; i++){Point

随便推点

关于OpenCV中图片旋转的问题-getRotationMatrix2D warpAffine_操吴戈兮被犀甲的博客-程序员秘密

关于OpenCV的图片旋转问题背景介绍测试案例正常图片如下(484*237):正常的调用旋转方法后:按照width和height交换的方式旋转之后解决方案so 结束讨论。。。不知道以后的OpenCV版本会不会改变~背景介绍使用opencv旋转图片需要用到两个API: - getRotationMatrix2D -设置旋转中心,旋转角度,缩放因子等,返回Mat作为后一个api的参数。 - w...

1043: [HAOI2008]下落的圆盘_anjiang8171的博客-程序员秘密

Time Limit:10 SecMemory Limit:162 MBSubmit:1725Solved:743[Submit][Status][Discuss]Description  有n个圆盘从天而降,后面落下的可以盖住前面的。求最后形成的封闭区域的周长。看下面这副图, 所有的红色线条的总长度即为所求.Input  第一行为1个整...

Chrome接口调试插件、浏览器接口调试插件、浏览器接口调试工具_浏览器调试工具接口_crap_cn的博客-程序员秘密

apiDebug-API接口调试插件,开源API接口调试插件,Restfull接口调试软件,Restfull接口调试插件,谷歌API接口调试插件,Chrome浏览器接口调试插件,POST请求模拟插件,api接口调试工具,开源接口调试工具,POST模拟工具插件地址:https://chrome.google.com/webstore/detail/apimanager-crapapi/ieoej

OpenWRT的包依赖 package DEPENDS 类型_openwrt package 依赖_★临★的博客-程序员秘密

本文为转载好文:原文链接:OpenWRT的包依赖 package DEPENDShttp://blog.chinaunix.net/uid-27057175-id-5011775.htmlOpenWRT平台的package管理有自己的Makefile,不同于gcc的Makefile,这个Makefile是作为OpenWRT强大的package管理的关键组件。要想往OpenWRT添加自己的...

正则表达式匹配关键字_sdnjiejie65的博客-程序员秘密

 正则匹配字符串  function reg() {   alert("1");  var bodyobject=document.body.innerHTML;  var keycode="上海利众集团 上海利众 利众集团 利众";  keycode=keycode.replace(/( +)/g,"|");  bodyobject=bodyobject.replace(eval("/("+ke

gcc提高程序性能的几个参数_gcc 性能指标_浪里狼的博客-程序员秘密

-o3 -o1 -o2这三个参数依据数字的增加性能提高越大,但是需要注意,用该参数进行提升性能,编译后的代码虽然性能提高,但是代码执行顺序也许和最初代码设计的顺序不一样。-funroll-loopsgcc来检查代码,进行循环展开,减少循环次数提高性能

推荐文章

热门文章

相关标签