基于Python实现快速排序、冒泡排序、选择排序、桶排序


基于Python实现快速排序、冒泡排序、选择排序

快速排序

复杂度:快速排序是不稳定的排序算法,最坏的时间复杂度是 O(n2),最好的时间复杂度是(nlogn)

方法一

代码:

import random


def quick_sort(lst):
    if len(lst) < 2:  # 递归的基例或出口,即列表长度为1时返回自身
        return lst
    else:
        pivot = lst[0]  # 以第一个元素作为参考
        less = [x for x in lst[1:] if x <= pivot]  # 得到小于等于参考元素的列表
        greater = [x for x in lst[1:] if x > pivot]  # 得到大于参考元素的列表
        return quick_sort(less) + [pivot] + quick_sort(greater)  # 对于上面得到的两个列表继续递归排序


if __name__ == '__main__':
    list1 = list(range(10))
    random.shuffle(list1)
    print("排序前: ", list1)
    print("排序后: ", quick_sort(list1))

结果:

排序前:  [7, 6, 0, 9, 8, 5, 2, 1, 3, 4]
排序后:  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

方法二

讲道理这个方法比较难以理解,实在理解不了可以忽略不管。
代码:

import random


def quick_sort(lst, start, end):
    """
    找到基准值, 将小于基准值的元素放前面, 大于基准值的元素放后面, 两头向中间收缩, 重叠处就是基准值的实际位置
    """
    if start >= end:
        return
    pivot = lst[start]  # 基准值, 用于比对
    low = start
    high = end

    while low < high:
        # high不断向左收缩,从右往左找到第一个小于基准值的元素
        while low < high and lst[high] >= pivot:
            high -= 1
        lst[low] = lst[high]  # 将上述找到的元素与low互换位置,将比pivot小的放到前面去
        # 然后low不断向右收缩,找到第一个大于基准值的元素
        while low < high and lst[low] < pivot:
            low += 1
        lst[high] = lst[low]  # 将上述找到的元素与high互换位置,将比pivot大的放到后面去
    # 根据while条件,循环结束后,low与high收缩到同一个位置,而这个位置就是pivot的真实位置
    lst[low] = pivot
    # 至此,我们为pivot找到了正确的位置,同时pivot左侧的元素都比pivot小,右侧都比pivot大,但两侧还不是有序的

    # 对基准值左侧排序
    quick_sort(lst, start, low - 1)
    # 对基准值右侧排序
    quick_sort(lst, low + 1, end)


if __name__ == '__main__':
    list1 = list(range(10))
    random.shuffle(list1)
    print("排序前: ", list1)
    quick_sort(list1, 0, len(list1) - 1)
    print("排序后: ", list1)

结果:

排序前:  [8, 3, 2, 0, 9, 4, 6, 1, 7, 5]
排序后:  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
方法三

这是在菜鸟上看到的方法,同样是原地排序,思想跟方法二其实类似,但实现方法略有不同
代码:

def partition(arr, low, high):
    """在arr列表的low-high索引范围内,把比pivot小的元素放到pivot前面,同时给pivot(这里是拿high对应的元素)找到正确的位置,那么比pivot大的元素就在pivot后面了"""
    i = low  # 预置pivot的正确位置
    pivot = arr[high]
    for j in range(low, high):
        # 遍历low-high范围,找出有多少个元素比pivot小,同时把这些元素交换位置,放到前面,那么i也就对应着pivot实际的位置
        if arr[j] <= pivot:
            arr[i], arr[j] = arr[j], arr[i]
            i = i + 1
    # 到这里i也就对应着pivot实际的位置,然后将pivot(high对应的元素)与i互换
    arr[i], arr[high] = arr[high], arr[i]
    return i

# 快速排序函数
def quickSort(arr, low, high):
    if low < high:
        pi = partition(arr, low, high)  # pi是原来arr里high元素对应的正确位置,执行完后已经交换位置
        # 经过这一步,arr已经经过一次粗略排序:pi之前的都是小于arr[pi]的元素,pi之后都是大于arr[pi]的元素,但pi前后的元素还未排序
        quickSort(arr, low, pi - 1)  # 针对pi之前的元素再次执行快排
        quickSort(arr, pi + 1, high)  # 针对pi之后的元素再次执行快排

arr = [10, 7, 8, 9, 1, 5]
n = len(arr)
quickSort(arr, 0, n - 1)
print("排序后的数组:")
for i in range(n):
    print("%d" % arr[i]),

冒泡排序

复杂度:时间复杂度为 O(n^2),且排序是稳定的
代码:

import random


def bubble_sort(lst):
    """
    每次遍历列表,都将最大的数往后移动
    :param lst:
    :return:
    """
    for i in range(len(lst)-1, 0, -1):
        for j in range(i):  # 遍历列表前n个元素,根据i依次减小
            if lst[j] > lst[j+1]:
                lst[j], lst[j+1] = lst[j+1], lst[j]  # 如果相邻两个元素的顺序不正确,则替换它们的位置

if __name__ == '__main__':
    list1 = list(range(10))
    random.shuffle(list1)
    print("排序前: ", list1)
    bubble_sort(list1)
    print("排序后: ",list1)

结果:

排序前:  [3, 9, 2, 6, 1, 4, 8, 0, 5, 7]
排序后:  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

选择排序

复杂度:时间复杂度为 O(n^2),且排序是稳定的
代码:

import random


def select_sort(lst):
    """
    每次遍历列表,都选择列表中最小的元素,将其移到列表最前面
    :param lst: 
    :return: 
    """
    for i in range(len(lst)):
        smallest_index = i  # 每次遍历列表的起始位置为i,同时假定i就是最小的元素索引
        for j in range(i, len(lst)):  # 以i为起始值,即忽略前一次遍历选择出来的最小元素
            if lst[smallest_index] > lst[j]:
                smallest_index = j  # 如果列表中有比smallest_index对应元素更小的元素,则将这个更小元素的索引赋值给smallest_index
        # 遍历后的smallest_index对应的元素就是最小的元素,将其移动到本次遍历的起始位置
        lst[i], lst[smallest_index] = lst[smallest_index], lst[i]

if __name__ == '__main__':
    list1 = list(range(10))
    random.shuffle(list1)
    print("排序前: ", list1)
    select_sort(list1)
    print("排序后: ", list1)

结果:

排序前:  [3, 7, 6, 4, 0, 9, 2, 8, 5, 1]
排序后:  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

桶排序

桶排序的基本思想是将一个数据表分割成许多 buckets,然后每个 bucket 各自排序。也是典型的 divide-and-conquer 分而治之的策略。
桶排序是稳定的,而且桶排序非常快,但是同时也非常耗空间,基本上是最耗空间的一种排序算法

代码:

import random


def bucket_sort(lst):
    max_num = max(lst)  # 获得最大的元素
    bucket = [0] * (max_num+1)  # 根据最大元素建立n个桶
    for i in lst:
        bucket[i] += 1  # 遍历列表每一个元素,在对应位置的桶中增加计数
    sorted_list = []  # 创建结果列表
    for j in range(len(bucket)):
        if bucket[j] != 0:
            for k in range(bucket[j]):
                sorted_list.append(j)  # 按顺序遍历每个桶,从桶中取数放到结果列表中
    return sorted_list


if __name__ == '__main__':
    lst1 = [i for i in range(10)]
    random.shuffle(lst1)
    print("排序前: ", lst1)
    print("排序后: ", bucket_sort(lst1))

结果:

排序前:  [9, 2, 8, 4, 3, 6, 0, 1, 7, 5]
排序后:  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

插入排序

插入排序的基本思想是本质是从第二个开始取数,跟前面的比较并插入正确的位置
插入排序是稳定的,时间复杂度为 O(n)到O(n^2)

代码:

import random


def insert_sort(l):
    for i in range(1, len(l)):  # 从头开始
        for j in range(i, 0, -1):
            if l[j-1] > l[j]:  # 一点一点往前插
                l[j-1], l[j] = l[j], l[j-1]
            else:
                break  # 排序从头开始,如果它没有前一个数大,那它就不需要改变位置
    return l


if __name__ == '__main__':
    lst1 = [i for i in range(10)]
    random.shuffle(lst1)
    print("排序前: ", lst1)
    print("排序后: ", insert_sort(lst1))

结果:

排序前:  [9, 2, 8, 4, 3, 6, 0, 1, 7, 5]
排序后:  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值