python常用排序算法

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)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值