快速排序

C语言实现

#include <stdio.h>
#define N 9
int A[N] = { 10, -3 , 28, 76, 37, 55, -1, 99, 11};
void printArr(int arr[], int length)
{
    int i;
    for (i = 0; i < N; i++)
    {
        printf("%d ", A[i]);
    }
    printf("\n");
}
void quick_sort(int a[],int numsize) //a是整形数组,numsize是元素个数 
{ 
    int i = 0, j = numsize-1;
    int val = a[0];//指定参考值val大小
    if(numsize>1)//确保数组长度至少为2,否则无需排序 
    {
        while(i<j)//循环结束条件
        {

            for( ; i < j; j--) //从后向前搜索比val小的元素,找到后填到a[i]中并跳出循环 
                if(a[j]<val)
                {
                    a[i]=a[j];
                    printf("参考值%d,前 <-- 后 找a[j--]<%d的元素| ", val, val);
                    printArr(a, numsize);
                    break;
                }
            for(;i<j;i++)//从前往后搜索比val大的元素,找到后填到a[j]中并跳出循环 
                if(a[i]>val)
                {
                    a[j]=a[i];
                    printf("参考值%d,前 --> 后 找a[i++]>%d的元素| ", val, val);
                    printArr(a, numsize);
                    break;
                }
        }
        a[i]=val; //将保存在val中的数放到a[i]中
        printf("参考值%d,整理结果\t\t     | ", val);
        printArr(a, numsize);
        quick_sort(a,i); //递归,对前i个数排序 
        quick_sort(a+i+1,numsize-1-i); //对i+1到numsize这numsize-1-i个数排序 
    }

}
int main()
{
    quick_sort(A, N);
    return 0;
}

运行结果
[root@centos6 data]# gcc test.c
[root@centos6 data]# ./a.out
原数列| 10 -3 28 76 37 55 -1 99 11
参考值10,前 <– 后 找a[j–]<10的元素| -1 -3 28 76 37 55 -1 99 11
参考值10,前 –> 后 找a[i++]>10的元素| -1 -3 28 76 37 55 28 99 11
参考值10,整理结果 | -1 -3 10 76 37 55 28 99 11
参考值-1,前 <– 后 找a[j–]<-1的元素 | -3 -3 10 76 37 55 28 99 11
参考值-1,整理结果 | -3 -1 10 76 37 55 28 99 11
参考值76,前 <– 后 找a[j–]<76的元素 | -3 -1 10 11 37 55 28 99 11
参考值76,前 –> 后 找a[i++]>76的元素| -3 -1 10 11 37 55 28 99 99
参考值76,整理结果 | -3 -1 10 11 37 55 28 76 99
参考值11,整理结果 | -3 -1 10 11 37 55 28 76 99
参考值37,前 <– 后 找a[j–]<37的元素| -3 -1 10 11 28 55 28 76 99
参考值37,前 –> 后 找a[i++]>37的元素| -3 -1 10 11 28 55 55 76 99
参考值37,整理结果 | -3 -1 10 11 28 37 55 76 99

下标012345678
A[N]-3-110113728557699

结果分析

假设有两个指针,i指向开始,j指向结束。i从前向后运动做比较,j从后向前运动做比较,当两者交集的时候,比较结束。
1.参考值10
这是最开始的情况,将数组第一个元素A[0]作为参考值,另找一变量保存该值,i=0
10 -3 28 76 37 55 -1 99 11
1>后–>前
然后,先从后往前找小于10的数,j递减,i=0,j=8

下标 i1234567 j
A[N]10-328763755-19911

11比10大,不符合条件,略过,继续向前找,i=0,j=7

下标 i123456j8
A[N]10-328763755-19911

99比10大,不符合条件,略过,继续向前找,i=0,j=6

下标 i12345j78
A[N]10-328763755-19911

-1比10小,符合条件,将-1拷贝到参考值10的位置A[i]去,则此时A[j]位置的数据已经没有意义了,我们可以将它置0或者不管也行,将来会将别的值拷贝到此位置,i=0,j=6

下标 i12345j78
A[N]-1-328763755-19911

停止当前方向查找,转向从前往后找。
2>前–>后
接上一步,这次以原来参考值所在位置A[0+1],从前向后查找大于10的数,i递增,i=1,j=6

下标0i2345j78
A[N]-1-328763755-19911

-3比10小,不符合条件,略过,继续向后找,i=2,j=6

下标01i345j78
A[N]-1-328763755-19911

28比10大,符合条件,将28拷贝A[j]去,则此时A[i]位置的数据已经没有意义了,我们可以将它置0或者不管也行,将来会将别的值拷贝到此位置,i=2,j=6

下标01i345j78
A[N]-1-328763755289911

停止当前方向查找,此时发现i依然小于j,对参考值10的整理还没有结束。再转向从后往后前查找,直到i和j相遇为止。
3>后–>前
接上一步,这次从后往前找小于10的数,j递减,i=2,j=5

下标01i34j678
A[N]-1-328763755289911

55比10大,不符合条件,略过,继续向前找,i=2,j=4

下标01i3j5678
A[N]-1-328763755289911

37比10大,不符合条件,略过,继续向前找,i=2,j=3

下标01ij45678
A[N]-1-328763755289911

76比10大,不符合条件,略过,继续向前找,i=2,j=2
当i=2,j=2时,此时发现i和j相遇了,则停止查找。
4>参考值归位
i和j已经相遇,将参考值10拷贝到A[i]的位置

下标01i=i345678
A[N]-1-310763755289911

至此,对参考值10的整理已经结束,可以看到10的左侧都是小于10的数,10的右侧都是大于10的数。
这这是完成了第一轮整理,接下来,还要分两部分递归,将10的左侧{A[0]~A[1]}和10的右侧{A[3]~A[8]}作为子集,分别按以上相同的步骤递归调用函数整理。
2.参考值-1
整理过程就不写了,与参考值10的过程一样,这里直接给出整理完成的结果

下标012345678
A[N]-3-110763755289911

3.参考值76

下标012345678
A[N]-3-110763755289911

4.参考值11
这个没有可移动的,跳过
5.参考值37

下标012345678
A[N]-3-110112837557699

至此整个排序结束,已经是有序队列!


始于2008-10-19,西理工;更新至2016-06-05,杭州。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值