算法基础:快速排序(基于Python)

本博客所有内容均整理自《算法图解》,欢迎讨论交流~

快速排序是一种常用的排序算法,比选择排序快很多。C语言标准库中的函数qsort实现的就是快速排序。

快速排序非常实用,它使用了递归和分治法的思想。具体来说,快速排序的思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列的目的。

下面来用数组元素排序的例子详细阐述快速排序。

对排序算法来说,最简单的数组是怎样的呢?很明显,就是根本不需要排序的数组,即空数组和只包含一个元素的数组。

因此,快速排序的基线条件为数组为空或只包含一个元素。在这种情况下,根本就不需要排序,只需要原样返回数组即可。

def quicksort(array):
    if len(array) < 2:
        return array

那么对于更长的数组呢?

其实思路很简单,对于更长的数组,我们就想办法让它一步步简化,直到也变成最简单的数组即可。这就是快速排序应用分治法思想的方案。具体操作步骤如下:

首先,我们从数组中选择一个元素,这个元素被称为基准值。对于如何选择合适的基准值,我们在此不做介绍,此时我们暂且将数组的第一个元素作为基准值

然后,我们找出比基准值小的元素以及比基准值大的元素。这个过程被称为分区。于是现在,你有以下三组数据:

  1. 一个由所有小于基准值的数字组成的子数组;
  2. 基准值;
  3. 一个由所有大于基准值的数字组成的子数组。

这里需要注意,我们以上的操作只进行了分区,得到的两个子数组是无序的。当然,如果这两个数组是有序的,对整个数组进行排序就非常容易了,我们只需要执行以下操作即可以得到一个有序的数组:
左边的数组  + 基准值 + 右边的数组 = 有序数组

那么如何对子数组进行排序呢?我们沿用递归的思路,即如果子数组的长度小于2,我们可以直接返回数组作为排好序的序列,而如果数组长度大于2,我们继续选择基准值,并将该子数组划分成更小的子数组。

所以,快速排序的算法步骤如下所示:

  1. 选择基准值。
  2. 将数组分成两个子数组:小于基准值的元素和大于基准值的元素。
  3. 对这两个子数组进行快速排序。

举个实际的例子。

假设你要对以下4个数字进行排序:

33, 10, 15, 7

首先,我们取第一个元素33作为基准值,记作基准值1,于是,我们可以得到以下两个子数组:

小于基准值的元素:10, 15, 7    ——记作数组1

大于基准值的元素:无              ——记作数组2

很明显,小于基准值的元素组成的子数组包含3个元素,我们需要对其进行递归,再次使用快速排序。

于是,我们再次选择子数组的第一个元素10作为基准值,记作基准值2,得到以下两个数组:

小于基准值的元素:7                ——记作数组3

大于基准值的元素:15              ——记作数组4

对于这两个子数组,我们可以直接返回原数组作为已排序序列,所以数组1排序后为:

数组3 + 基准值2 + 数组4 = 数组1(已排序)= 7, 10, 15

获得了已排序的数组1之后,我们再来看数组2,由于数组2是空数组,所以我们也是可以直接返回原数组作为已排序数组。于是我们可以得到已排序的原始数组为:

数组1(已排序)+ 基准值1 + 数组2(已排序) = 原始数组(已排序)= 7, 10, 15, 33

于是就把原来的数组成功完成了排序工作。

下面给出快速排序的Python代码:

def quicksort(array):
    if len(array) < 2:
        return array
    else:
        pivot = array[0]
        less = [i for i in array[1:] if i < pivot]
        greater = [i for i in array[1:] if i > pivot]
        return quicksort(less) + [pivot] + quicksort(greater)

细心的朋友可能会说,如果原数组中包含相同的数字,而我们刚好把该数字选做了基准值怎么办呢?其实解决这个问题的方法很简单,我们只需要在划分子数组时,把小于改成小于等于(或把大于改成大于等于)即可。因为我们是在array[1:]中去寻找与array[0]的大小关系的元素,所以array[0]一定会出现在最后[pivot]的位置;而与array[0]相等的数字会被分入子数组,依次参与递归。

所以将以上代码修改一个地方即可,如下所示:

def quicksort(array):
    if len(array) < 2:
        return array
    else:
        pivot = array[0]
        less = [i for i in array[1:] if i <= pivot]
        greater = [i for i in array[1:] if i > pivot]
        return quicksort(less) + [pivot] + quicksort(greater)

如此,我们便可以去给任何无序数组进行排序了,哪怕其中有相等的数字。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值