快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

比如一个无序的序列a[7]:

4 6 8 9 3 1 5

l:0  r:6

现在我们要对它做降序排列

1. 定义两个位置标记l和r在要排序部分的左右两边,(这里是0号和6号),  先选定第一个元素4作为一个比较的基准值,

2.然后从右往左找一个大于4的数,这里是5。然后把右标记指向5也就是a[6],(其实原来的j就标记了这)。这时我们把r和l标记的两个数a[r]和a[l]交换。交换完成后,就变成了这样:

5 6 8 9 3 1 4 

l:0  r:6

3. 然后从左到右找一个小于4的数,这里是3。然后让左标记指向它,然后交换a[l]与a[r]。交换完成后,就变成了这样:

5 6 8 9 4 1 3

l:4  r:6

然后重复第2步,让 r 从现在的位置向左移动找到一个大于4的数,这时我们发现l和r相遇了,这样我们就得到了一个特殊的数组----以元素4为界,它左边的数总是大于4的,它右边的数总是小于4的。这时我们把数组取出2份,左边一份是所有大于4的数,是a[0]~a[3]。然后右边一份是所有小于4的数,a[5]~a[6]。

然后我们分别让这两个子序列进行上面的操作:

对于左边部分a[0]~a[3]:5 6 8 9

选定左边第一个数a[0],也就是5为基准值,然后让所有比5大的数都在5左边,让所有比5小的数都在5右边。

得到:6 8 9 5

然后再继续分,递归地执行这个过程(让所有比基准值大的数都在基准值左边,所有比基准值小的数都在基准值右边),然后直到不能再分了。

这时我们就能得到一个降序的序列。

具体实现如下:

//LR表示要排序部分的左右边界,如果要排序一个10个元素的数组,就调用QuickSort(0,10);
void QuickSort(int L, int R)        
{
    //设置两下标,分别为要排序部分的开始和结束元素的数组下标
    int l = L, r = R - 1;    
    if (l >= r) return;
    int key = a[L];            //以序列第一个元素为基准
    while (l < r)
    {
        //让右边的下标r从右往左找到第一个小于key的数
        while (a[r] <= key&&r>l) r--;//从右往左找到一个比key大的值
        swap(&a[r], &a[l]);        //交换左右两个下标位置的值
        if (l == r)break;        //如果l等于r,就结束循环
        //让左边的下标l从左往右找到第一个大于key的数
        while (a[l] >= key&&r>l)l++;//从左往右找到一个比key小的值
        swap(&a[r], &a[l]);        //交换左右两个下标位置的值
        if (l == r)break;        //如果l等于r,就结束循环
    }
    
    //上面的部分已经让r==l,
    //并且所有比key小的数都在key的左边,所有比key大的数都在key右边
    QuickSort(L, r);
    QuickSort(r+1, R);
}

上面代码是实现降序的,如果想实现升序,只要把两个while里面的>=和<=互换。

这里有一个例子,随机生成50000个数,然后降序输出

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define N 50000

int a[N];

void init()//初始化数组
{
    srand((unsigned)time(NULL));
    for (int i = 0; i < N; i++)
    {
        a[i] = rand();
    }
}
void print()                //输出数组元素
{
    int i;
    for (i = 0; i < N;i++)
        printf("%d ",a[i]);
    printf("\\n");
}

void swap(int*a, int*b)//交换两个变量的值
{
    int c = *a;
    *a = *b;
    *b = c;
}

//LR表示要排序部分的左右边界,如果要排序一个10个元素的数组,就调用QuickSort(0,10);
void QuickSort(int L, int R)        
{
    //设置两下标,分别为要排序部分的开始和结束元素的数组下标
    int l = L, r = R - 1;    
    if (l >= r) return;
    int key = a[L];            //以数组第一个元素为基准
    while (l < r)
    {
        //让右边的下标r从右往左找到第一个小于key的数
        while (a[r] <= key&&r>l) r--;
        swap(&a[r], &a[l]);        //交换左右两个下标位置的值
        if (l == r)break;        //如果l等于r,就结束循环
        //让左边的下标l从左往右找到第一个大于key的数
        while (a[l] >= key&&r>l)l++;
        swap(&a[r], &a[l]);        //交换左右两个下标位置的值
        if (l == r)break;        //如果l等于r,就结束循环
    }
    
    //上面的部分已经让r==l,
    //并且所有比key小的数都在key的左边,所有比key大的数都在key右边
    QuickSort(L, r);
    QuickSort(r+1, R);
}

int main()
{
    init();
    printf("数组原来是这样的:\\n");
    print();
    QuickSort(0,N);
    printf("\\n排序后:\\n");
    print();
    system("pause");
}