快速排序-详解附Python代码

排序思路

  1. 取一个元素P(第一个元素),目标是使得元素P归位;
  2. 列表被元素P分成了两个部分,左边的比P小,右边的比P大;
  3. 分别再对左右两个部分的列表重复1,2步骤,递归完成排序

重点:如何定义一个归位函数,将序列中的元素P(第一个)归位,使得左变得所有元素比P小,右边得所有元素比P大。

评价:
时间复杂度
最坏情况: O ( n 2 ) O(n^2) O(n2) # 输入的序列刚好是逆序的情况(每次归为后只产生一条序列)
平均情况:​​ O ( n l o g n ) O(n logn) O(nlogn)
最好情况: O ( n l o g n ) O(n logn) O(nlogn)

空间复杂度
平均情况: O ( n l o g n ) O(n logn) O(nlogn)
最坏情况: O ( n ) O(n) O(n)

稳定性:不稳定。排序过程中不是相邻两位交换。

快速排序示意图
在这里插入图片描述

定义归位函数

# 定义归位函数,每次将首元素归位并返回对应的序号
def partition(lst, left, right):
    """思路:
        定义left、right指针,首先将left指针的值传给temp,至此left指针”空缺“。
    while(左右指针没有相遇):
        (1)从right指针开始移动寻找比temp小的值,放到left所指的”空缺“。完成后right”空缺“
        (2)从left指针开始移动寻找比temp大的值,放到right所指的”空缺“。完成后left”空缺“
    """
    # 将首元素用临时变量存放
    temp = lst[left]
    # 用双指针移动归位,left指针向右移动,right指针向左移动,相等后结束。
    while left < right:
        # 操作right指针向左走
        while left < right and lst[right] >= temp:
            right -= 1  # 向左走
        lst[left] = lst[right]  # 寻找比temp小的值,放到left所指的”空缺“

        # 操作left指针向右走
        while left < right and lst[left] <= temp:
            left += 1
        lst[right] = lst[left]

    # left=right,循环结束temp归位
    lst[left] = temp
    return left

定义递归函数

递归函数思路:

  • 结束条件:列表只有一个元素(递归条件就是左右指针不相等)
  • 循环部分:归位传入的序列,并将左右两个部分也归位。
def quick_sort(lst, left, right):
    # 只有lst有两个及以上元素
    if left < right:
        # 归位后返回归为元素的序号
        mid = partition(lst, left, right)
        quick_sort(lst, left, mid - 1)
        quick_sort(lst, mid + 1, right)

lst = [1, 9, 7, 4, 5]
quick_sort(lst, 0, len(lst) - 1)
print(lst)

完整代码

import time
import random


def calculate_time(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        execution_time = end_time - start_time
        print(f"函数 {func.__name__} 的执行时间为:{execution_time} 秒")
        return result

    return wrapper


# 定义归位函数,每次将首元素归位并返回对应的序号
def partition(lst, left, right):
    """思路:
        定义left、right指针,首先将left指针的值传给temp,至此left指针”空缺“。
    while(左右指针没有相遇):
        (1)从right指针开始移动寻找比temp小的值,放到left所指的”空缺“。完成后right”空缺“
        (2)从left指针开始移动寻找比temp大的值,放到right所指的”空缺“。完成后left”空缺“
    """
    # 将首元素用临时变量存放
    temp = lst[left]
    # 用双指针移动归位,left指针向右移动,right指针向左移动,相等后结束。
    while left < right:
        # 操作right指针向左走
        while left < right and lst[right] >= temp:
            right -= 1  # 向左走
        lst[left] = lst[right]  # 寻找比temp小的值,放到left所指的”空缺“

        # 操作left指针向右走
        while left < right and lst[left] <= temp:
            left += 1
        lst[right] = lst[left]

    # left=right,循环结束temp归位
    lst[left] = temp
    return left


def _quick_sort(lst, left, right):
    # 只有lst有两个以上元素
    if left < right:
        # 归位后返回归为元素的序号
        mid = partition(lst, left, right)
        _quick_sort(lst, left, mid - 1)
        _quick_sort(lst, mid + 1, right)


@calculate_time
def quick_sort(lst):
    _quick_sort(lst, 0, len(lst) - 1)


if __name__ == '__main__':
    # 测试代码
    lst = list(range(10000))
    random.shuffle(lst)
    print(lst)
    quick_sort(lst)
    print(lst)

快速排序+二分查找

def partition(lst, left, right):
    temp = lst[left]
    while left < right:
        while left < right and lst[right] >= temp:
            right -= 1
        lst[left] = lst[right]
        while left < right and lst[left] <= temp:
            left += 1
        lst[right] = lst[left]

    lst[left] = temp

    return left


arr = [5, 2, 8, 6, 3]

print(partition(arr, 0, len(arr) - 1))


def quick_sort(lst, left, right):
    if left < right:
        mid = partition(lst, left, right)
        quick_sort(lst, left, mid)
        quick_sort(lst, mid + 1, right)


quick_sort(arr, 0, len(arr) - 1)
print(arr)


#  二分查找只适用于在有序序列中查找元素
def binary_search(lst, val):
    left = 0
    right = len(lst) - 1
    while left <= right:
        mid = (left + right) // 2
        if lst[mid] == val:
            return mid
        elif lst[mid] > val:  # 说明要查找的值在mid的左边
            right = mid - 1
        else:  # 说明要查找的值在mid的右边、
            left = mid + 1
    # 代码执行至此说明没有找到元素val,返回-1
    return -1
# 注意:mid定义在while循环里面


print(binary_search(arr, 8))

输出:
2
[2, 3, 5, 6, 8]
4

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

现实、狠残酷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值