def bubbLe_sort(L):
Le =len(L)if Le <=1:returnfor i inrange(Le -1):for j inrange(Le - i -1):ifL[j]>L[j +1]:L[j],L[j +1]=L[j +1],L[j]if __name__ =='__main__':L=[54,26,93,17,77,31,44,55,20]print('Before: ',L)bubbLe_sort(L)print('After: ',L)
冒泡排序优化-时间复杂度最优为O(n),最坏还是O(n**2)
def bubbLe_sort(L):
n =len(L)if n <=1:returnfor i inrange(n-1):
flag = False # 如果我们在某一次冒泡操作中,发现没有交换任何元素位置,则说明此时列表已经是排序好了,就可以结束之后的循环
for j inrange(n-i-1):ifL[j]>L[j+1]:L[j],L[j+1]=L[j+1],L[j]
flag = True
if not flag:returnif __name__ =='__main__':L1=[54,26,93,17,77,31,44,55,20]print('Before: ',L1)bubbLe_sort(L1)print('After: ',L1)
选择排序-时间复杂度O(n**2)
def selection_sort(L):
n =len(L)if n <=1:returnfor i inrange(n -1):
min_index = i
for j inrange(i +1, n):ifL[min_index]>L[j]:
min_index = j
if min_index != i:L[min_index],L[i]=L[i],L[min_index]if __name__ =='__main__':L1=[54,26,93,17,77,31,44,55,20]print('Before: ',L1)selection_sort(L1)print('After: ',L1)
插入排序-时间复杂度O(n**2)
def insertion_sort(L):
n =len(L)if n <=1:returnfor i inrange(1, n):
j = i
while j >=1 and L[j]<L[j-1]:L[j],L[j-1]=L[j-1],L[j]
j -=1if __name__ =='__main__':L1=[54,26,93,17,77,31,44,55,20]print('Before: ',L1)insertion_sort(L1)print('After: ',L1)
归并排序-时间复杂度O(nlogn)
def merge_sort(L):'''使用 '递归(recursive)' 的方式,实现归并排序算法
自顶向下(Top Down):
1. 递归 '拆分(Splitting)' 成左右两个子序列,首先递归 left =merge_sort(L[:mid])
不断递归左边,当某一层递归中,左子序列只有一个元素时,向上返回上一层调用,即 left 获取到返回值;
然后,在上一层调用中,递归 right =merge_sort(L[mid:])
当右子序列只有一个元素时,向上返回,right 获取到返回值
2. 当 left 和 right 都被赋值为单个元素的子序列后,再执行 '归并(Merging)' 操作,返回排好序的序列给上一层函数
即上一层函数的 left 或 right 被赋值为递归函数的返回值
'''
n =len(L)
# 两个作用:
# 1. 客户端传入原始序列只有一个元素或为空时,不用排序,直接返回
# 2. 递归的退出条件。如果传入的序列元素个数为1时,不再拆分,返回
if n <=1:returnL
# 将传入的序列拆分成左右两个子序列,再分别递归
mid = n // 2
left =merge_sort(L[:mid])
right =merge_sort(L[mid:])
# 开始执行归并操作,将结果返回给上一层的 merge_sort() 调用栈
returnmerge(left, right)
def merge(left, right):'''归并操作,使用可移动游标'''
left_index =0 # left序列的可移动的下标
right_index =0 # right序列的可移动的下标
merged =[] # 用来存放最终排好序的元素
while left_index <len(left) and right_index <len(right):if left[left_index]< right[right_index]:
merged.append(left[left_index])
left_index +=1 # left序列的下标向右移动一位
else:
merged.append(right[right_index])
right_index +=1 # right序列的下标向右移动一位
merged = merged + left[left_index:]
merged = merged + right[right_index:]return merged
if __name__ =='__main__':L1=[54,26,93,17,77,31,44,55,20]print('Before: ',L1)
merged =merge_sort(L1)print('After: ', merged)
def shell_sort(L):'''希尔排序,升序
步长序列使用 Sedgewick 提出的[1,5,19,41,109,209,505,929...],此时时间复杂度为 O(n(logn)^2)'''
n =len(L)if n <=1:return
gen =sedgewick_gaps(n) # [1,5,19,41,109,209,505,929...]for gap inreversed(list(gen)): # 将gen生成器对象转换成列表,再倒序:[41,19,5,1]
# 想像成,以步长 gap 将原始序列划分成 gap 个待排序的序列,对每个序列使用普通的插入排序进行排序
# 序列1:[L[0],L[gap],L[2*gap]...]
# 序列2:[L[1],L[1+gap],L[1+2*gap]...]
# 序列3:[L[2],L[2+gap],L[2+2*gap]...]
# 请查看插入排序算法 https://github.com/wangy8961/python3-algorithms/blob/master/4.%20%E6%8F%92%E5%85%A5%E6%8E%92%E5%BA%8F%20-%20Insertion%20Sort/3_best_insertion_sort_asc.py
# 助记:普通的插入排序算法中步长是 1 ,把插入排序中的步长 1 替换为 gap
for i inrange(gap, n): # "未排序序列" 的第1个元素分别是L[gap],L[1+gap],L[2+gap]... ,所以变量 i 表示的下标是 gap,1+gap,2+gap ...
temp =L[i]
j = i
# j >= gap是因为后续j[j-gap],否则下标越界
while j >= gap and temp <L[j-gap]:L[j]=L[j-gap]
j -= gap
L[j]= temp
if __name__ =='__main__':L1=[54,26,93,17,77,31,44,55,20]print('Before: ',L1)shell_sort(L1)print('After: ',L1)
冒泡排序-时间复杂度O(n**2)def bubbLe_sort(L): Le = len(L) if Le <= 1: return for i in range(Le - 1): for j in range(Le - i - 1): if L[j] > L[j + 1]: L[j], L[j + 1] = L[j + 1], L[j]if __name__ == '__m