快速排序

    快速排序算法是基于分治策略的一种排序算法。基本思想是,对于输入的子数组a[left : right],按以下三个步骤进行排序:

    (1)分解。以a[left]为基准元素将a[left : right]分成三段,a[left : p-1],a[p], a[p+1 : right]。使得a[left : p-1]中的任何一个元素小于a[p],a[p+1 : right]中的任何一个元素大于a[p]。下标p在划分的过程中确定。

    (2)递归求解。通过递归调用快速排序算法分别对a[left : p-1]和a[p+1 : right]进行排序。

    (3)合并。由于a[left : p-1]和a[p+1 : right]已经排好序了,所以a[left : right]不需任何计算,就已排好序。

    代码如下:

#include <stdio.h>

void quick_sort(int[], int, int);
int partition(int[], int, int);
void swap(int*, int*);

int main()
{
    int a[20],i=0;
    srand(5);
    while(i<20)    a[i++] = (int)rand();    i=0;
    printf("Before sort:\n");
    while(i<20)    printf("%d\n", a[i++]);  i=0;
    quick_sort(a, 0, 19);
    printf("\nAfter sort:\n");
    while(i<20)    printf("%d\n", a[i++]);
    return 0;
}

void quick_sort(int a[], int left, int right)
{
    int p;
    if(left < right)
    {
        p = partition(a, left, right);
        quick_sort(a, left, p-1);   //对左半段排序
        quick_sort(a, p+1, right);  //对右半段排序
    }
}

int partition(int a[], int left, int right)
{
    int i=left, j=right+1, x=a[left];
    while(1)
    {
        while((a[++i] < x) && (i < right)); //从左边开始找一个比x大的元素
        while(a[--j] > x);                  //从右边开始找一个比x小的元素
        if(i >= j)  break;                  //如果较大元素的下标比较小元素的大,则说明已完成划分
        swap(&a[i], &a[j]);
    }
    a[left] = a[j];
    a[j] = x;
    return j;                               //返回基准元素的下标
}

void swap(int *a, int *b)
{
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

    上述算法中的partation( )函数,用来以一个确定的基准元素a[left](也就是第一个元素)对子数组a[left : right]进行划分。是快速排序算法的关键。

    有些细节需要注意。例如,算法中的下标 i 和 j 不会超出a[left : right]的下标界。另外,在快速排序算法中选取a[left]作为基准可以保证算法正常结束。如果选择a[right]作为划分的基准,且a[right]又是a[left : right]中最大的元素,则partition( )返回的值为right,这就会使quick_sort陷入死循环。

    对于输入序列a[left : right],partition的计算时间显然为O(r-p-1)。

    快速排序的运行时间与划分是否对称有关,器最坏情况发生在划分过程产生的两个区域分别包含n-1个元素和1个元素的时候。这时的时间复杂度为O(n^2)。在最好的情况下,每次划分所去的基准都恰好为中值,即每次划分都产生两个大小为n/2的区域,这时时间复杂度为O(n log n)。

    运行结果如下:

Before sort:
590011675
99788765
2131925610
171864072
317159276
171035632
602511920
963050649
1069979073
1919854381
33661026
589806848
2086105860
475191198
894416410
550050020
780437020
583787226
893281828
550277486


After sort:
33661026
99788765
171035632
171864072
317159276
475191198
550050020
550277486
583787226
589806848
590011675
602511920
780437020
893281828
894416410
963050649
1069979073
1919854381
2086105860
2131925610

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值