排序算法分类
比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。
非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,需要开辟额外的存储空间,因此也称为线性时间非比较类排序。
冒泡排序——交换类排序
冒泡排序(Bubble Sort)也是一种简单直观的排序算法。
它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。
走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。
代码如下:
def bubbleSort(arr):
for i in range(1, len(arr)):
for j in range(0, len(arr)-i):
if arr[j] > arr[j+1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr
if __name__ == '__main__':
list = [1, 5, 8, 123, 22, 54, 7, 99, 300, 222]
print("List source is:", list)
result = bubbleSort(list)
print("List sort is:", result)
快速排序——交换类排序
快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。
通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
算法描述
①从数列中挑出一个元素,称为 “基准”(pivot); ②重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
③递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
代码参考:
def quickSort(arr, left=None, right=None):
left = 0 if not isinstance(left,(int, float)) else left # isinstance判断一个对象是否是一个已知的类型(int、float),是这个元组里的类型就返回true
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)
return index-1
def swap(arr, i, j):
arr[i], arr[j] = arr[j], arr[i]
if __name__ == '__main__':
list = [6,1,2,7,9,3,4,5,10,8]
print("List source is:", list)
result = quickSort(list)
print("List sort is:", result)
用列表[6,1,2,7,9,3,4,5,10,8]为例进行快速排序,基准为6,left为0,right为9,进入partition函数:
Index = left+1 = 1,i = index = 1,判断i=1 小于right=9,判断arr[i] = 1小于arr[0] = 6,交换arr[i] 和arr[index],列表不变;
Index = index + 1 = 2,i = i + 1 = 2,判断i=2小于right=9,判断arr[i] = 2小于arr[0] = 6, 交换arr[i]和arr[index],列表不变;
3.Index = index + 1 = 3,i = i + 1 = 3,判断i=3小于right=9,判断arr[i] = 7不小于arr[0] = 6,列表不变;
Index = index = 3,i = i + 1 = 4,判断i=4小于right=9,判断arr[i] = 9不小于arr[0] = 6,列表不变;
Index = index = 3,i = i + 1 = 5,判断i=5小于right=9,判断arr[i] = 3小于arr[0] = 6, 交换arr[i=5]和arr[index=3],列表变为[6,1,2,3,9,7,4,5,10,8];
Index = index + 1 = 4,i = i + 1 = 6,判断i=6小于right=9,判断arr[i] = 4小于arr[0] = 6, 交换arr[i=6]和arr[index=4],列表变为[6,1,2,3,4,7,9,5,10,8];
Index = index + 1 = 5,i = i + 1 = 7,判断i=7小于right=9,判断arr[i] = 5小于arr[0] = 6, 交换arr[i=7]和arr[index=5],列表变为[6,1,2,3,4,5,9,7,10,8];
Index = index + 1 = 6,i = i + 1 = 8,判断i=8小于right=9,判断arr[i] = 10不小于arr[0] = 6,列表不变;
Index = index = 6,i = i + 1 = 9,判断i=9等于right=9,判断arr[i] = 8不小于arr[0] = 6,列表不变;
交换arr[0]和arr[5],列表变为[5,1,2,3,4,6,9,7,10,8],返回index-1=5此时,第一个基准6已经在准确的位置了,其左边的数都比自身小,右边的数都比自身大。
参考链接
https://zhuanlan.zhihu.com/p/172524701
https://blog.csdn.net/u014597198/article/details/91395700