文章内容源于链接: 菜鸟教程算法.
一、冒泡排序
算法步骤
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
什么时候最快
当输入的数据已经是正序时(都已经是正序了,我还要你冒泡排序有何用啊)。
什么时候最慢
当输入的数据是反序时(写一个 for 循环反序输出数据不就行了,干嘛要用你冒泡排序呢,我是闲的吗)。
代码实现
def bubbleSort(arr):
for i in range(1, len(arr)):#循环,每次循环提出最大值放末尾
change = False#设置一个change变量,当arr不在变化是,停止排序
for j in range(0, len(arr)-i):#len(arr)-i不能为len(arr)
if arr[j] > arr[j+1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
change = True
print(arr)
if not change:
break
return arr
arr=[5,8,6,1,7,3,9,4,2,10]
bubbleSort(arr)
二、选择排序
算法步骤
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
重复第二步,直到所有元素均排序完毕。
注意
选择排序是一种简单直观的排序算法,无论什么数据进去都是 O(n²) 的时间复杂度。所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧
代码实现
def selectionSort(arr):
for i in range(len(arr) - 1):#每次循环,找出最小值
minIndex = i #记录最小索引
for j in range(i+1, len(arr)):#找出最小索引
if arr[j] < arr[minIndex]:
minIndex = j
# i不是最小数时,将i和最小数交换
if i != minIndex:
arr[i],arr[minIndex]= arr[minIndex],arr[i]
print(arr)
arr=[5,8,6,1,7,3,9,4,2,10]
selectionSort(arr)
#和冒泡排序相反,每次找出最小值放入开头
三、 插入排序
算法步骤
将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
代码实现
def insertionSort(arr):
for i in range(len(arr)):
preIndex = i -1#前一个元素索引
current = arr[i]#当前元素值
while preIndex >= 0 and arr[preIndex] > current:#把当前值与前面元素值对比
arr[preIndex+1] = arr[preIndex]
preIndex -=1 #每次减一个索引,使值能继续与前面元素对比,直到碰到比自己小的数
arr[preIndex+1] = current
print(arr)
return arr
arr=[5,8,6,1,7,3,9,4,2,10]
insertionSort(arr)
#插入排序每次排序排出i个排好的数值,放于开头
四、希尔排序
概念
希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;
但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位;
希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。
算法步骤
选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1;
按增量序列个数 k,对序列进行 k 趟排序;
每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
代码实现
def shellSort(arr):
import math
gap = 1
while(gap < len(arr)/3):#
gap = gap*3 + 1
while gap > 0:
for i in range(gap,len(arr)):#插入排序
temp = arr[i]
j = i-gap
while j >= 0 and arr[j] > temp:
arr[j+gap] = arr[j]
j -= gap
arr[j+gap] = temp
print(arr)
gap = math.floor(gap/3)#向下获取最大整数
return
arr=[5,8,6,1,7,3,9,4,2,10]
shellSort(arr)
#希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本
五、归并排序
算法步骤
申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
设定两个指针,最初位置分别为两个已经排序序列的起始位置;
比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
重复步骤 3 直到某一指针达到序列尾;
将另一序列剩下的所有元素直接复制到合并序列尾。
代码实现
def mergeSort(arr):
import math
if(len(arr)<2):
return arr
middle = math.floor(len(arr)/2)
left,right=arr[0:middle],arr[middle:]
return merge(mergeSort(left),mergeSort(right))
def merge(left,right):
result= []
while left and right:
if left[0] <= right[0]:
result.append(left.pop(0))
else:
result.append(right.pop(0))
while left:
result.append(left.pop(0))
while right:
result.append(right.pop(0))
print(result)
return result
arr=[5,8,6,1,7,3,9,4,2,10]
mergeSort(arr)
#算法步骤:(merge既是该算法实例)
#
# 设定两个指针,最初位置分别为两个已经排序序列的起始位置;
#
# 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
#
# 重复步骤 3 直到某一指针达到序列尾;
#
# 将另一序列剩下的所有元素直接复制到合并序列尾。
接下来就是快排了,也就是我要发的最后一个排序算法,因为堆排序我无法看懂,后面四个就没有去看了
六、快速排序
算法步骤
从数列中挑出一个元素,称为 “基准”(pivot);
重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;
代码实现
def quickSort(arr, left=None, right=None):
left = 0 if not isinstance(left,(int, float)) else left
right = len(arr)-1 if not isinstance(right,(int, float)) else right
if left < right:
partitionIndex = partition(arr, left, right)
quickSort(arr, left, partitionIndex-1)
quickSort(arr, partitionIndex+1, right)
return arr
#算法主要函数
def partition(arr, left, right):
pivot = left #基数
index = pivot+1#索引,直至碰到大于基数值停止增加,
i = index
while i <= right:
if arr[i] < arr[pivot]:
swap(arr, i, index)
index+=1
i+=1
swap(arr,pivot,index-1)#基数值移到中间,其左侧所有值小于他,右侧所有值大于他
print(arr)
return index-1
def swap(arr, i, j):
arr[i], arr[j] = arr[j], arr[i]
arr=[5,8,2,1,7,3,9,4,2,10]
quickSort(arr)
print(arr)