快速排序

S-{v}是一种分治算法,步骤如下:

1.若数组S中元素个数是0或者1,返回

2.取S中的一个元素v,作为枢纽元

3.将S - {v}中分成两个不相交的集合,S_{1}=\left \{ x\in S-\left [ v \right ],x\leqslant v \right \}S_{1}=\left \{ x\in S-\left [ v \right ],x\geq v \right \}

4.返回quicksort(S1),继随v,继而quicksort(S2)

快速排序性能的关键是枢纽元的选择,最好的枢纽元是恰好将元素分成2份,几种选择:

1.使用第一个元素,不好,很容易对一段预排序的数组进行O(N ^2)时间处理

2.使用随机元素,可以解决第一个问题,但是随机数开销太大,比排序时间大的多

3.三数中值分割法,使用左、中、右3个位置的元素的中值

代码如下:

#include <stdio.h>

#define cutoff   3

static void Swap(int *a, int *b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

/* 取3个数的中值,并移动到right - 1的位置,因为right已经在比枢纽元大的位置上了 */
int Median3(int *a, int left, int right)
{
    int center = (left + right) / 2;

    /* 效果是,a[left] <= a[center] <= a[right] */
    if (a[left] > a[center])
        Swap(&a[left], &a[center]);
    if (a[left] > a[right])
        Swap(&a[left], &a[right]);
    if (a[center] > a[right])
        Swap(&a[center], &a[right]);

    /* 将枢纽元移动到right - 1的位置上并返回枢纽元的值 */
    Swap(&a[center], &a[right - 1]);
    return a[right - 1];
}

/* 快速排序递归核心例程 */
void QSort(int *a, int left, int right)
{
    int i, j;
    int Pivot;

    if (left + cutoff <= right)
    {
        /* 获取枢纽元 */
        Pivot = Median3(a, left, right);
        i = left, j = right - 1;

        for (;;)
        {
            /* 这里必须这样处理,否则若i,j两个位置的元素和枢纽元相等,那么死循环
                这样写保证了每次先移动i和j */
            while (a[++i] < Pivot);
            while (a[--j] > Pivot);
            if (i < j)
                Swap(&a[i], &a[j]);
            else
                break;
        }
        Swap(&a[i], &a[right - 1]);

        /* 处理左右两边 */
        QSort(a, left, i - 1);
        QSort(a, i + 1, right);
    }
    else
    {
    //只有不到3个元素,用插入排序,其实可以放大比例,比如1000个元素以内使用插入排序
    }
}

/* 快速排序外部接口 */
void QuickSort(int *a, int N)
{
    QSort(a, 0, N - 1);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值