快速排序算法

Posted 2019wxw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速排序算法相关的知识,希望对你有一定的参考价值。

分而治之D&C

分而治之不是一种解决问题的算法,而是一种希望问题分解,将复杂的问题划分为多个简单问题来解决的思想。

分而治之的思想重点:

(1)找出简单的基线条件

(2)确定如何缩小问题的规模,使其符合基线条件。

快速排序

例如快速排序问题,一个列表进行排序,如下图

技术图片

首先选择列表中的一个元素作为基准元素,其他的元素都与这个元素做比较,找出小于这个基准值的值、大于基准值的值。这称为“分区”,这时有,

1)一个由所有小于基准值的数字组成的子数组;

2)基准值

3)一个由所有大于基准值的数组组成的子数组

技术图片

然后再将“小于v”和“大于v”的数据块作为子数组,同样选择基准值,再进行上述类似操作,当执行到数据块中只有1个元素或者0个元素时,即完成排序。

这个问题中的基线条件是执行到数据块中只有1个或者0个元素;

例如下面的数组,进行排序:

技术图片

根据选择的基准值,对这个数组进行分区的各种可能方式如下:

技术图片

假设你将3用作基准值,可对得到的子数组进行快速排序。

技术图片

还有一个例子,如下图:


             技术图片

技术图片

算法复杂度

看一下其他的算法的复杂度(O表示法表示)

技术图片

快速排序的性能高度依赖于你选择的基准值。

最糟情况:算法复杂度O(n^2)

假设总是将第一个元素用作基准值,且要处理的数组是有序的。由于快速排序算法不检查输入数组是否有序,因此它依然尝试对其进行排序。

技术图片

注意,数组并没有被分成两半,相反,其中一个子数组始终为空,这导致调用栈非常长。

这个示例展示的是最糟情况,在最糟情况下,栈长为O(n),在调用栈的每层都涉及O(n)个元素,完成每层所需的时间都为O(n)。因此整个算法需要的时间为O(n) * O(n) = O(n^2)。

最佳情况:算法复杂度O(n log n)

假设总是将中间的元素用作基准值,在这种情况下,调用栈如下。

技术图片

调用栈短得多!因为每次都将数组分成两半,所以不需要那么多递归调用。很快就到达了基线条件,因此调用栈短得多。

这个示例展示的是最佳情况,在最佳情况下,栈长为O(log n),每一层运行时间为O(n),所以整个算法需要的时间为O(n) * O(log n) = O(n log n)。

平均情况:算法复杂度O(n log n)

最佳情况也是平均情况。只要每次都随机地选择一个数组元素作为基准值,快速排序的平均运行时间就将为O(n log n)。快速排序是最快的排序算法之一,也是D&C典范。

如何选择基准值?

实现快速排序时,请随机地选择用作基准值的元素。快速排序的平均运行时间为O(n log n)。

总结

1)D&C将问题逐步分解。使用D&C处理列表时,基线条件很可能是空数组或只包含一个元

素的数组。

2)实现快速排序时,请随机地选择用作基准值的元素。快速排序的平均运行时间为O(n log n)。

3)大O表示法中的常量有时候事关重大,这就是快速排序比合并排序快的原因所在。

快速排序详解:http://c.biancheng.net/view/198.html

实例:

#include <stdio.h>
int qusort(int s[],int start,int end)    //自定义函数 qusort()
{
    int i,j;    //定义变量为基本整型
    i=start;    //将每组首个元素赋给i
    j = end;    //将每组末尾元素赋给j
    s[0]=s[start];    //设置基准值
    while(i<j)
    {
        while(i<j&&s[0]<s[j])
        j--;    //位置左移
        if(i<j)
        {
            s[i]=s[j];    //将s[j]放到s[i]的位置上
            i++;    //位置右移
        }
        while(i<j&&s[i]<=s[0])
            i++;    //位置左移
        if(i<j)
        {
            s[j]=s[i];    //将大于基准值的s[j]放到s[i]位置
            j--;    //位置左移
        }
    }
    s[i]=s[0];    //将基准值放入指定位置
    if (start<i)
        qusort(s,start,j-1);    //对分割出的部分递归调用qusort()函数
    if (i<end)
        qusort(s,j+1,end);
    return 0;
}

int main()
{
    int a[11], i;    //定义数组及变量为基本整型
    printf("请输入10个数:\\n");
    for(i=1;i<=10;i++)
        scanf("%d",&a[i]);    //从键盘中输入10个要进行排序的数
    qusort(a,1,10);    //调用qusort()函数进行排序
    printf("排序后的顺序是:\\n");
    for(i=1;i<=10;i++)
        printf("%5d",a[i]);    //输出排好序的数组
    printf("\\n");
    return 0;
}

运行结果:

  技术图片

以上是关于快速排序算法的主要内容,如果未能解决你的问题,请参考以下文章

一行Python代码搞定快速排序算法

排序算法 | 快速排序(含C++/Python代码实现)

交换排序(冒泡排序快速排序的算法思想及代码实现)

快速排序/快速选择算法

快速排序算法详解及代码实现

排序算法——快速排序的图解代码实现以及时间复杂度分析