优化快速排序的几种方法

本文介绍了快速排序的基本思想和算法实现,并详细讨论了四种优化方法:1) 引入随机性选择主元;2) 数据聚集;3) 三位数取中策略;4) 结合插入排序。通过对不同优化策略的测试,分析了它们对排序效率的影响,特别是在处理有序或重复数据时的效果。
摘要由CSDN通过智能技术生成

快速排序

1.基本思想

快速排序采用分治思想。经过一趟排序将待排序序列分割为独立的两部分,其中一部分的所有排序关键字均小于另一部分的所有排序关键字,再按上述方法对序列的两部分分别进行快速排序,整个排序过程可以递归执行,最终达到整个序列有序的目的。

2.算法概述

分解:在待排序数列按照某种特定选取一个元素作为主元。利用主元对序列进行重排,使得序列分成独立的两个部分,其中一部分的所有排序关键字均小于另一部分的所有排序关键字,即序列所有排序关键字小于主元的排序关键字的元素置于主元的左侧,其他元素置于右侧。

解决:通过递归对主元左侧的序列已经右侧的序列进行快速排序来去求解子问题。
合并:因为快速排序是原址操作,所以不需要执行合并操作,同时也节省了部分空间。

3.算法实现(Python)
# coding = utf-8

"""
快速排序的一些优化方式
"""
import random
import time


def quick_sort(lst, first=0, last=0):
    # 快速排序
    if first >= last:
        return lst
    low = first
    high = last
    pivot = lst[first]  # 选取第一个为主元
    while first < last:
        while first < last and lst[last] >= pivot:
            last -= 1
        lst[first] = lst[last]
        while first < last and lst[first] <= pivot:
            first += 1
        lst[last] = lst[first]
    lst[last] = pivot
    quick_sort(lst, low, first - 1)
    quick_sort(lst, first + 1, high)
4. 算法分析

运行时间
快速排序的最坏时间复杂度是Θ(n2),平均情况下的时间复杂度为Θ(nlgn)。快速排序的渐近时间复杂度介于最坏情况和平均情况。
这里分别采用确定的快速排序(即选取序列的第一个元素或最后一个序列为主元)分别针对输入规模>500万的序列进行排序,获得确定的快速排序的运行时间。

输入规模500万的序列排序运行时间

算法 随机序列 重复序列 升序序列 降序序列
确定的快速排序 36084ms 递归深度过大,堆栈溢出 同左 同左
python内置sort方法 5372ms 93ms 184ms 99ms

测试数据分析
在针对输入序列的数据是随机的时,我们设计的快速排序的效率是可以接受的。针对输入序列是有序的时候,虽然因为递归深度过大,导致堆栈溢出(Python的解释器没有针对做优化),无法成功执行完程序,但是我们也可以预料到,每次排序划分长度都是1,也就是说我们需要将序列划分500万次,才能使序列重新有序,其时间复杂度和空间复杂度可想而知。此时的情况为最坏的情况即时间复杂度为Θ(n2),即沦为普通的冒泡排序。在实际情况中,输入序列很有可能是有序的或者是部分有序的,这时我们可以通过在算法中引入随机性,使得算法对所有的输入都能获得较好的期望性能,同时将随机化版本的快速排序被更多的人运用在大数据输入情况下的排序算法。


优化方式1:引入随机性

随机选取主元元素

# coding = utf-8

"""
优化方法1:引入随机性
"""

import random
import time


def quick_sort(lst, first=0, last=0):
    # 快速排序
    if first >= last:
        return lst
    low = first
    high = last
    pivot_index = random.randint(first, last)  # 随机选取主元位置
    lst[first], lst[pivot_index] = lst[pivot_index], lst[first]  # 将主元置于首位
    pivot = lst[first]
    while first < last:
        while first < last and lst[last] >= pivot:
            last -= 1
        lst[first] = lst[last]
        while first < last and lst[first] <= pivot:
            first += 1
  
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值