排序算法:冒泡排序,选择排序,插入排序,快速排序+递归,希尔排序,归并排序,基数排序
# -*- coding: utf-8 -*-
# 排序算法
# 冒泡排序 从第一个数开始,相邻两个数相比较,如果后面的数小于前面的数,两数就交换位置,否则第二个和第三个数比较,一轮过后最后一个数就是最大的,
# 默认为顺序 reversed 为True 时为逆序
def bubble_sort(l, reversed=None):
for j in range(len(l) - 1, -1, -1): # j为比较次数 遍历次数为len(l)-1
for i in range(j):
if (l[i] > l[i + 1] and reversed == None) or (l[i] < l[i + 1] and reversed == True):
l[i], l[i + 1] = l[i + 1], l[i] # 交换值,将较小的值往前移动
return l
# 另一种写法
# def bubble_sort(l,reversed=None):
# for j in range(len(l) - 1): #遍历次数
# for i in range(len(l) - j - 1): #比较次数
# if (l[i] > l[i + 1] and reversed == None) or (l[i] < l[i + 1] and reversed == True):
# l[i], l[i + 1] = l[i + 1], l[i]
# return l
# 将第一个数与后面的数相比较,如果比第一个数小,就调换位置,最后第一个数就是最小的,然后在从第二个数开始比较,
# 选择排序
def select_sort(l, reversed=None):
for i in range(len(l) - 1): # 遍历次数
for j in range(i + 1, len(l)): # 从索引 i+1 比较到最后一个数
if (l[i] > l[j] and reversed == None) or (l[i] < l[j] and reversed == True):
l[i], l[j] = l[j], l[i]
return l
# 插入排序法 适合原始记录的键值大部分已经排好序的情况下
def insert_sort(l, reversed=None):
for i in range(1, len(l)):
previous = l[i - 1] # 取出第一个数为previou
current = l[i] # 取出第二个数为current
while (i >= 1 and current < previous and reversed == None) or (i >= 1 and current > previous and reversed == True):
l[i], l[i - 1] = previous, current # 如果当前的数小于 前一个数,就交换位置
i -= 1
previous = l[i - 1] # 将previou 和current 向前移一位,然后再比较
current = l[i]
return l
# 快速排序 + 递归
def quick_sort(l):
if len(l) >= 2:
middle = l[len(l) // 2] # 取中间值为基数
left, right = [], [] # 新建两个列表来存储 小于基数的数 和大于或等于基数的数
l.remove(middle) # 抽取基数
for value in l:
if value >= middle:
right.append(value)
else:
left.append(value)
return quick_sort(left) + [middle] + quick_sort(right) # 递归
else:
return l
# 希尔排序
# 插入排序的升级版
def shell_sort(l, reversed=None):
interval = len(l) // 2 # 设置间隔interval
while interval != 0:
# for i in range(len(l) - 1, interval - 1, -1): # 从后往前开始遍历
i = len(l) - 1
previous = l[i - interval] # 于最后一个数间隔 len(l)//2 的数为previous
current = l[i] # 设置最后一个数为current
while i >= interval:
if (previous > current and reversed == None) or (previous < current and reversed == True):
l[i - interval], l[i] = l[i], l[i - interval] # 满足条件就交换
i -= 1
previous = l[i - interval] # 向前移动
current = l[i]
interval = interval // 2 # 缩小间隔
# 上面的代码将大部分数据值都已经排序好,下面调用插入排序
insert_sort(l) #最后用插入排序
return l
# 归并(合并)排序(一般用于已排序好的两个或者两个以上的数列)
# 还没有实现逆序
def merge_sort(l1, l2, reversed=None):
# 先用选择排序将两个列表排好序
select_sort(l1)
select_sort(l2)
l = []
index1 = 0
index2 = 0
for i in range(len(l1) + len(l2) - 2):
if l1[index1] < l2[index2]:
l.append(l1[index1])
index1 += 1
else:
l.append(l2[index2])
index2 += 1
return l
# 基数排序
# 不能排序负数
def cardinal_sort(l, reversed=None):
max_l = max(l)
size = 1
while max_l >= 10**size: #得到列表 l 中最大的数的位数
size += 1
for s in range(size):
bucket = [[] for i in range(10)] # 创建10个桶
for value in l:
bucket[value // (10**s) % 10].append(value) # 根据位数(0-9)找到自己所在桶的位置,并放进去,相当于一轮排序
if reversed == None:
l = [j for i in bucket for j in i] # 将桶中经过一轮排序后的数放回 列表l 中
elif reversed == True:
bucket_new = bucket[::-1] # 用切片将桶中的元素翻转过来
l = [j for i in bucket_new for j in i] # 将桶中经过一轮排序后的数放回 列表l 中
return l
# l = [j for i in bucket for j in i]
# 相当于如下代码
# l = []
# for i in bucket:
# for j in i:
# l.append[j]
# def cardinal_sort(l, size):
# for s in range(size):
# bucket = [[] for i in range(10)] # 创建10个桶
# for value in l:
# bucket[value // (10**s) % 10].append(value) # 根据位数(0-9)找到自己所在桶的位置,并放进去,相当于一轮排序
# mount = 0
# for index in range(10): # 将桶中经过一轮排序后的 数放回列表中
# if len(bucket[index]) != 0:
# for data in bucket[index]:
# l[mount] = data
# mount += 1
# return l
代码测试
l1 = [100, -5, 7, 2, 9, 200, 101]
l2 = [100, -5, 7, 2, 9, 200, 101]
l3 = [100, -5, 7, 2, 9, 200, 101]
l4 = [100, -5, 7, 2, 9, 200, 101]
l5 = [100, -5, 7, 2, 9, 200, 101]
l6_1 = [20, 51, 45, 88, 9999]
l6_2 = [98, 10, 23, 15, 9999]
l7 = [100, 5, 7, 2, 9, 200, 101]
result1 = bubble_sort(l1, reversed=True)
print(result1)
result2 = select_sort(l2, reversed=True)
print(result2)
result3 = insert_sort(l3, reversed=True)
print(l3)
result4 = quick_sort(l4)
print(result4)
result5 = shell_sort(l5)
print(result5)
result6 = merge_sort(l6_1, l6_2)
print(result6)
result7 = cardinal_sort(l7, reversed=True)
print(result7)