参考书籍:《算法之美——Python语言实现》
学习Python算法的同学极力推荐此书
代码如下:
def BubbleSort(s1):
n=len(s1)
for i in range(n):
for j in range(n-i-1):
if s1[j]>s1[j+1]:
s1[j],s1[j+1] = s1[j+1],s1[j]
l1=[9,0,6,5,3,10,36,2,1]
print('排序前的数列:',l1)
BubbleSort(l1)
print('排序后的数列:',l1)
代码输出:
排序前的数列: [9, 0, 6, 5, 3, 10, 36, 2, 1] 排序后的数列: [0, 1, 2, 3, 5, 6, 9, 10, 36]
代码解释:
函数中的第一个for循环语句:控制循环次数。
函数中的第二个for循环语句:每一次执行时,相当于对列表进行了一次切片操作(只遍历了前n-i个元素哦),每次循环都将最大元素放在n-i位(索引从0开始),当然还有其他衍生动作但是并不重要
代码如下:
def SelectSort(arr):
n = len(arr)
for i in range(n-1):
mid = i
for j in range(i,n-1):
if arr[mid]>arr[j+1]:
mid = j+1
arr[i],arr[mid] = arr[mid],arr[i]
s1 = [3,18,0,32,2,1]
print('排序前的数列:',s1)
SelectSort(s1)
print('排序后的数列:',s1)
代码输出:
排序前的数列: [3, 18, 0, 32, 2, 1] 排序后的数列: [0, 1, 2, 3, 18, 32]
代码解释:
整个程序目的是去寻找小的数字,将其放在前面.
第一个for语句:第一步:记录此时元素的下标(索引从0)开始。第二步:进行for循环的语句(此for语句目的是去为了寻找记录元素的下标到末尾中的最小元素下标)。第三步:将已记录元素下标对应元素互换位置。整个大的循环执行n-1次。
代码如下:
def InsertSort(arr):
n=len(arr)
for i in range(1,n):
c1=arr[i]
j=i
while j>0 and c1
代码输出:
排序前的数列: [9, 3, 1, 5, 6]
排序后的数列: [1, 3, 5, 6, 9]
代码解释:
循环n次:对于每次循环记录当前下标对应元素以及当前下标。对比当前下标小的下标对应元素进行遍历。如果元素比记录元素大就将记录元素赋值变为当前元素然后继续遍历直至循环退出同时这里找到退出循环时的下标,将下标对应的元素赋值变为开始记录元素。
这三个排序算法的时间程度其实是一样的。个人感觉这三个虽然变来变去的,本质还是挨个去找。没啥意思
四:希尔算法
代码如下:
def SellSort(arr):
n=len(arr)
space=n//3
while space>0:
for i in range(space,n):
key=arr[i]
j=i
while j>=space and arr[j-space]>key:
arr[j]=arr[j-space]
j-=space
arr[j]=key
space-=1
s1=[18,3,0,5,2,10,7,15,38,100]
print('排序前的数列:',s1)
SellSort(s1)
print('排序后的数列:',s1)
代码输出:
排序前的数列: [18, 3, 0, 5, 2, 10, 7, 15, 38, 100]
排序后的数列: [0, 2, 3, 5, 7, 10, 15, 18, 38, 100]
代码解释:
代码中的space//3可以换成space//n(n可以取一个合适的数)这个数可直接影响希尔排序效率。在这里列表长度为10,步长即3。第一个循环while循环:对步长3,2,1依次进行遍历。第二个for循环对每次的循环记录下标及其对应元素。第三个循环while循环寻找距离记录下标整数倍的步长的下标及其对应元素。如过该元素比记录元素大啊,就将记录下标对应元素赋值变为当前元素并且记录当前下标,终止最后while循环后,将当前下标对应元素赋值为一开始记录元素。每次for的循环其实只完成一次对调。
个人感觉希尔排序是最难理解的排序,参考书的作者也写错了。
五:快速排序
代码如下:
def MovePivot(arr,low,high):
Pivot=arr[high]
imove=low-1
for i in range(low,high):
if arr[i]<=Pivot:
imove+=1
arr[imove],arr[i]=arr[i],arr[imove]
arr[imove+1],arr[high]=arr[high],arr[imove+1]
return imove+1
def QuickSort(arr,low,high):
if low
代码输出:
排序前的数列 [10, 3, 28, 4, 12, 20]
快速排序数列 [3, 4, 10, 12, 20, 28]
代码解释:
这个代码采用递归思想,如果读者不会递归,读者可以参考我的另外两篇文章:Python:递归算法(基础) Python:递归算法(深入)好了回到快速排序上吧!QuickSort()这个函数为主要函数。MovePivot()这个函数为执行函数。先分析QuickSort() 这个函数接收三个参数列表,起始查找下标,终止查找下标。对于第一次的执行,列表就不用我说吧,起始查找下标为0,终止查找下标为列表长减1。第一步:主要函数执行执行函数,执行函数开始执行循环,对于每次循环执行一次调换,以遍历的切片列表最后一个元素为标,小的去放前面,大的去放后面。执行函数将切片列表最后的一个元素放在记录的分界处。执行函数最后返回分界元素下标。对于第二步与第三步即下标前后的列表切片进行递归。知道顶层设计使用递归真心方便。
六:归并排序
代码如下:
def MergeSort(arr):
if len(arr) <= 1:
return arr
mid=len(arr)//2
left=MergeSort(arr[:mid])
right=MergeSort(arr[mid:])
return Merge(left,right)
def Merge(left,right):
r,l=0,0
temp=[]
lmax=len(left)
rmax=len(right)
while l
代码输出:
排序前数列 [1, 9, 10, 4, 50, 6, 7, 90, 21, 23, 45]
并归排数列 [1, 4, 6, 7, 9, 10, 21, 23, 45, 50, 90]
代码解释:
注意此段代码不是操作代码(不是对已给出列表执行操作)而是接受一个列表返回一个排序好的列表。这点在输出列表的时候会有不同。主要函数:MergeSort()第一步:判断列表长度是否为1,这段代码对于递归十分重要。将列表的长度尽量均分。对左边,对右边分别执行递归。递归完成后才返回列表。先后顺序十分重要。返回列表函数对接收的两个已经排序好的列表再次重新进行排序。返回列表函数包含一个循环对于两个列表***(因为已经排序好了,为什么已经排序好?(因为已经执行递归))***
这个循环很方便读者去理解,就不多赘述了。
***以上就是本次排序算法全部内容,如果喜欢,那就点个赞吧!***我在语言上有强迫症,所以有些语句在语文上是不对的。即使我知道也不会改变,因为改了心里莫名奇妙会很难受,但是问题不大,还请读者见谅。
等等,我忘记还有了,接下来就测试一下各大排序算法的时间吧!再顺便讲一个小错误。
问题:time.clock()无法被使用
原因:time库在更新时已舍去clock()函数,我们通过测试各大排序算法时间去了解一下解决方法吧!
测试数据如下:
ls=[100,3,28,38,200,30,1,49,2,600,52,232,66,99,2,69,420,59,77,87,93,212]
第一种方法:使用time库的perf_counter()函数
对于冒泡排序代码如下:
from time import perf_counter
ls=[100,3,28,38,200,30,1,49,2,600,52,232,66,99,2,69,420,59,77,87,93,212]
def BubbleSort(s1):
n=len(s1)
for i in range(n):
for j in range(n-i-1):
if s1[j]>s1[j+1]:
s1[j],s1[j+1] = s1[j+1],s1[j]
t1=perf_counter()
BubbleSort(ls)
t2=perf_counter()
print("%.8f"%(t2-t1))
对于冒泡排序代码输出:
0.00005980
第二种方法:使用time库的process_time()函数
对于选择排序代码如下:
from time import process_time
ls=[100,3,28,38,200,30,1,49,2,600,52,232,66,99,2,69,420,59,77,87,93,212]
def SelectSort(arr):
n = len(arr)
for i in range(n-1):
mid = i
for j in range(i,n-1):
if arr[mid]>arr[j+1]:
mid = j+1
arr[i],arr[mid] = arr[mid],arr[i]
t1=process_time()
SelectSort(ls)
t2=process_time()
print("%.8f"%(t2-t1))
对于选择排序代码输出:
0.00000000
。。。因为数据过小所以出现这样结果(你可以写一个for循环求累加和到10000,就会发现这个方法是正确的。这里还是使用较为精确的perf_counter()
对于选择排序代码输出:
0.00005940
对于插入排序代码输出:
0.00004680
对于希尔排序代码输出:
0.00005300
注意:希尔排序时间受到步长影响。
对于快速排序代码输出:
0.00006820
对于归并排序代码输出:
0.00016260
注意:归并排序不是操作函数是返回函数,所以输出时注意格式。
注释:这里数据结果出人意料,这是因为数据过小,当数据样本足够大,时间复杂程度才能体现出来(特别是在蓝桥杯赛场上(故意卡人就贼恶心))。
这一下应该就是真的结束了。喜欢或者认为有用的话,就点个赞再走吧!谢谢屏幕前的你,能够耐心看完。



