本文作为本人笔记之用,转载请注明出处!
一、冒泡排序
def bubble_sort(lis):
'''时间复杂度最低的冒泡排序'''
n = len(lis)
for i in range(n):
print(f'第{i}次----->{lis}')
exchange = False
for j in range(n-i-1):
if lis[j] > lis[j+1]:
lis[j],lis[j+1] = lis[j+1],lis[j]
exchange = True # 表示发生了交换
if exchange == False:
break
lis = [1,9,2,8,3,6,4,5,7]
print('排序前:',lis)
bubble_sort(lis)
print('排序后:',lis)
二、选择排序
def select_sort(lis):
n = len(lis)
for i in range(n):
print(f'第{i}次----->{lis}')
min_loc = i # 此轮最小的元素的索引,先默认当前元素的索引
for j in range(i+1,n):
if lis[j] < lis[min_loc]:
min_loc = j
lis[i],lis[min_loc] = lis[min_loc],lis[i]
lis = [1,9,2,8,3,6,4,5,7]
print('排序前:',lis)
select_sort(lis)
print('排序后:',lis)
三、插入排序
def insert_sort(lis):
n = len(lis)
for i in range(1,n): # 默认手上有第一张牌
print(f'第{i}次----->{lis}')
# 无序区(牌堆)拿到当前第一张牌(第i次抓第i张牌)
tmp = lis[i]
# 有序区(手上牌)最后一张牌的位置
j = i - 1 # j表示i的前一个元素
while lis[j] > tmp and j >= 0: # 判断前一个元素是否比当前元素(lis[i])大
lis[j+1] = lis[j] # j+1 等价于 i的位置,即把索引为j的元素往后移一位
j -= 1 # 往左边移一位
lis[j+1] = tmp
lis = [1,9,2,8,3,6,4,5,7]
print('排序前:',lis)
insert_sort(lis)
print('排序后:',lis)
四、快速排序
def partition(data,left,right):
# left是左边指针,right是右边指针
tmp = data[left]
while left < right:
while left < right and data[right] >= tmp:
right -= 1
data[left] = data[right]
while left < right and data[left] <= tmp:
left += 1
data[right] = data[left]
# 最后指针重合的位置就是tmp的最终位置,left/right都行
data[left] = tmp
# 返回left/right的位置
return left
def quick_sort(lis,left,right):
if left < right:
mid = partition(lis,left,right)
quick_sort(lis,left,mid-1) # mid位置的左边递归
quick_sort(lis,mid+1,right) # mid位置的右边递归
def quick_sort_s(lis):
return quick_sort(lis,0,len(lis)-1)
lis = [1,9,2,8,3,6,4,5,7]
print('排序前:',lis)
# quick_sort(lis,0,8)
quick_sort_s(lis)
print('排序后:',lis)
五、归并排序
def merge(left_lis,right_lis):
l_loc = 0
r_loc = 0
result = []
while l_loc < len(left_lis) and r_loc < len(right_lis):
if left_lis[l_loc] < right_lis[r_loc]:
result.append(left_lis[l_loc])
l_loc += 1
else:
result.append(right_lis[r_loc])
r_loc += 1
result += left_lis[l_loc:]
result += right_lis[r_loc:]
return result
def merge_sort_s(lis):
if len(lis) <= 1: # 递归结束条件
return lis
# 二分分解
num = len(lis)//2
left_lis = merge_sort_s(lis[:num])
right_lis = merge_sort_s(lis[num:])
# 归并
return merge(left_lis,right_lis)
lis = [3,4,54,3,2,3,44,5]
print('排序前:')
print(lis)
lis = merge_sort_s(lis)
print('排序后:')
print(lis)
六、希尔排序
def shell_sort(lis):
n = len(lis)
# 初始步长(即分多少组,步长要逐渐减少)
gap = n//2
while gap > 0:
print(f'gap:{gap}'.center(50,'-'))
print(lis)
for i in range(gap,n):
j = i
while j >= gap and lis[j-gap] > lis[j]:
lis[j-gap], lis[j] = lis[j], lis[j-gap]
j -= gap
# 每一次步长是上一次的一半
gap = gap // 2
lis = [7,5,4,6,3,8,2,9,1]
print('排序前:')
print(lis)
print('')
shell_sort(lis)
print('排序后:')
print(lis)
七、堆排序
def sift(data,low,finally_loc):
# finally_loc是最后一个元素的索引
i = low # low是最后一个元素的父节点
j = 2*i + 1 # 最后一个元素(左节点),或者最后一个元素的兄弟节点(左节点)
# 不知道是否是称职的领导
tmp = data[i]
# 判断是否称职
while j <= finally_loc: # 防止越界
# 找到孩子节点中的最大值
if j < finally_loc and data[j] < data[j+1]: # 如果左节点比右节点小
j += 1 # j定位到孩子节点中较大者的位置
# 判断是否称职
if tmp < data[j]: # 如果不称职
data[i] = data[j] # 孩子节点上位
i = j # 孩子的位置空了,其位置变成新的i(将要竞争的领导位置)
j = 2 * i +1 # 新的竞争的位置的左节点
else: # 如果称职
break
data[i] = tmp
def sift_sort(data):
n = len(data)
for i in range(n//2-1,-1,-1): # n//2-1 一定是最后一个元素的父节点
sift(data,i,n-1) # 构造大根堆
# 挨个出数
for i in range(n-1,-1,-1): # 根要存放的位置,从最后一个位置向前倒数
data[i],data[0] = data[0],data[i] # 根和要存放的位置互换,互换以后不再是堆,需要向下调整
sift(data,0,i-1)
lis = [7,5,4,6,3,8,2,9,1]
print('排序前:',lis)
sift_sort(lis)
print('排序后:',lis)
八、桶排序
def bucket_sort(lis):
# 构造桶
buckets = [0] * (max(lis)-min(lis)+1)
for i in range(len(lis)):
buckets[lis[i]-min(lis)] += 1
# 出数
res = []
for i in range(len(buckets)):
if buckets[i] != 0:
# [i + min(lis)]:桶所代表的元素,buckets[i]:桶里面的次数
res += [i + min(lis)] * buckets[i]
return res
lis = [1,9,2,8,3,6,4,5,7]
print('排序前:',lis)
lis = bucket_sort(lis)
print('排序后:',lis)