python常用排序算法
【考虑到注释太多视觉效果较低,故区分有无注释,文末附去注释脚本】
去注释版本:
import random
import time
import sys
def timer(func):
"""计时装饰器"""
t1 = time.time()
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
t2 = time.time()
print(f'<{func.__doc__}>总耗时:{round((t2 - t1) * 1000, 3)}ms')
return res
return wrapper
@timer
def bubble_sort(li):
"""冒泡排序"""
for i in range(len(li)):
flag = False
for j in range(len(li) - i - 1):
if li[j] > li[j + 1]:
li[j], li[j + 1] = li[j + 1], li[j]
flag = True
if not flag:
break
return li
@timer
def selection_sort(li):
"""选择排序"""
for i in range(len(li) - 1):
min_index = i
for j in range(i + 1, len(li)):
if li[min_index] > li[j]:
min_index = j
li[min_index], li[i] = li[i], li[min_index]
return li
def gen_list(_len=10, _min=0, _max=999):
"""生成指定范围指定长度的列表"""
return [random.randint(_min, _max) for _ in range(_len)]
@timer
def insert_sort(li):
"""插入排序"""
for i in range(1, len(li)):
temp = li[i]
j = i - 1
while j >= 0 and li[j] > temp:
li[j + 1] = li[j]
j -= 1
li[j + 1] = temp
return li
def get_mid(li, left, right):
"""快速排序分治具体实现"""
temp = li[left]
while left < right:
while left < right and li[right] >= temp:
right -= 1
li[left] = li[right]
while left < right and li[left] <= temp:
left += 1
li[right] = li[left]
li[left] = temp
return left
def quick_sort(li, left, right):
"""快速排序"""
if left < right:
mid = get_mid(li, left, right)
quick_sort(li, left, mid - 1)
quick_sort(li, mid + 1, right)
return li
if __name__ == '__main__':
arr = gen_list(1000)
print(f'默认最大递归调用次数:{sys.getrecursionlimit()}')
sys.setrecursionlimit(len(arr) + 2)
print(f'修改后的最大递归次数:{sys.getrecursionlimit()}')
print(bubble_sort(arr))
print(selection_sort(arr))
print(insert_sort(arr))
start = time.time()
print(quick_sort(arr, 0, len(arr) - 1))
finish = time.time()
print(f'<快速排序>总耗时:{round((finish - start) * 1000, 3)}ms')
带注释版本:
import random
import time
import sys
def timer(func):
"""计时装饰器"""
t1 = time.time()
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
t2 = time.time()
print(f'<{func.__doc__}>总耗时:{round((t2 - t1) * 1000, 3)}ms')
return res
return wrapper
@timer
def bubble_sort(li):
"""冒泡排序"""
for i in range(len(li)):
flag = False # 定义一个标志,如果没有发生变化,就说明已经排好
for j in range(len(li) - i - 1): # 后面的都是排好序的,就不必再来一次了
if li[j] > li[j + 1]: # 如果左边比右边大
li[j], li[j + 1] = li[j + 1], li[j] # 则交换位置
flag = True # 如果交换过,就把标志设置为True
if not flag: # 如果标志没有改变,说明上面的if没进去,就不需要继续交换了
break
return li
@timer
def selection_sort(li):
"""选择排序"""
for i in range(len(li) - 1): # 一共需要循环n-1次
min_index = i # 假设最小的就是当前索引位置的值
for j in range(i + 1, len(li)): # 内层循环,前i个都是排好序的
if li[min_index] > li[j]:
min_index = j # 循环找到最小值
li[min_index], li[i] = li[i], li[min_index] # 找到了最小的就和当前的交换位置
return li
def gen_list(_len=10, _min=0, _max=999):
"""生成指定范围指定长度的列表"""
return [random.randint(_min, _max) for _ in range(_len)]
@timer
def insert_sort(li):
"""插入排序"""
for i in range(1, len(li)): # 已经有一个元素,从第二个开始跟前面的比较
temp = li[i] # 临时变量,保存当前位置元素的值
j = i - 1 # 前一个(第一次循环的时候也就是第一个)
while j >= 0 and li[j] > temp: # 只要没到列表的最前面,且前一个大于当前位置的值
li[j + 1] = li[j] # 就将该元素后移一位
j -= 1 # 指针前移一位,继续比较
li[j + 1] = temp # 移动到了最左边,j=-1,j+1=0,将该元素放在索引0的位置上
return li
def get_mid(li, left, right):
"""快速排序分治具体实现"""
temp = li[left] # 先将最左边的数作为基准值
while left < right: # 只要左边的下标小于右边
while left < right and li[right] >= temp: # 从右边找到比基准值小的
right -= 1 # 游标左移一位
li[left] = li[right] # 在右边找到比基准值小的,放到基准值左边
while left < right and li[left] <= temp: # 从左变开始找比基准值大的
left += 1 # 右边右移一位
li[right] = li[left] # 在左边找到比基准值大的,放到基准值右边
li[left] = temp # 将基准值放回应该放的位置
return left # 最终left=right,返回的是中间位置的下标
# @timer # 这里用了递归,不适合用装饰器了,而且列表元素个数大于1000的时候会报递归超过最大值错误
def quick_sort(li, left, right):
"""快速排序"""
if left < right: # 只要左边下标小于右边
mid = get_mid(li, left, right) # 获取到中间位置的下标
quick_sort(li, left, mid - 1) # 递归调用,处理左边
quick_sort(li, mid + 1, right) # 递归调用,处理右边
return li
if __name__ == '__main__':
# arr = gen_list(10000)
arr = gen_list(1000)
print(f'默认最大递归调用次数:{sys.getrecursionlimit()}')
sys.setrecursionlimit(len(arr) + 2) # 设置最大递归调用次数,已有2次被占用
print(f'修改后的最大递归次数:{sys.getrecursionlimit()}')
print(bubble_sort(arr)) # 冒泡排序 # <冒泡排序>总耗时:8508.943ms
print(selection_sort(arr)) # 选择排序 # <选择排序>总耗时:11879.419ms
print(insert_sort(arr)) # 插入排序 # <插入排序>总耗时:11882.298ms
start = time.time()
print(quick_sort(arr, 0, len(arr) - 1)) # 快速排序
finish = time.time()
print(f'<快速排序>总耗时:{round((finish - start) * 1000, 3)}ms') # <快速排序>总耗时:4833.429ms
去单行注释脚本(仅供参考)
import re
def uncomment(file_name):
new_file_name = 'new_' + file_name
with open(file_name, 'r') as f:
data = f.readlines()
with open(new_file_name, 'w') as new_f:
for line in data:
if '#' in line:
new_data = re.sub('#.*', '', line)
new_f.write(new_data)
else:
new_f.write(line)