排序算法之快速算法


————————————————————————————————————————————————


你没有变强是因为你一直很舒服!


求知若饥,虚心若愚!

—————————————————————————————————————————————————


一 挖坑调整

快速排序,这也是在实际中最常用的一种排序算法,速度快,效率高。就像名字一样,快速排序是最优秀的一种排序算法。

快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。


方法的思想是:

1 先找一个基准值(理论上是可以随便找一个,但是做好选择第一个或者最后一个,方便理解,代码也简单)。

2对数组进行分区操作,小于基准的得数字都放到基准值的左边,大于等于基准值的数字都放到基准值的右边。

3此时基准值的位置已经确定,然后对两边的数字进行重复递归操作,使所有的数字都有序。


举例说明

2 2 4  9  3 6 7 15 取基准值是2,使用 i , j 两个指针分别从两边进行扫描,把比2小的元素和比2大的元素分开。首先比较2和5,5比2大,j左移一位

2  4  9  3 6 71 5  比较 2和1 ,2大于1,所以把1移动到2的位置。

 1  4  9  3 6 7 1 5   然后从左边开始比较,比2大的,移动到 之前 1 的位置。因为4大于2,所以4移动到之前1的位置。

 1  4  9  3 67 4 5  然后比较2和7, 2和6, 2和3, 2和9 都大于2,满足条件,所以第一轮比较结束。把2移动到最后的位置

最后的结果是   [1] 2 [ 9 3 6 7 4 5 ]


根据这个描述,我们先写一段代码实现如上的功能。

基本的编程思路是:我们先确定一个标志位(第一个元素),然后从右边开始依次和标志位比较。如果大于标志位则继续左移,如果小于标志位则移动到标志位,然后从右边开始比较,比标志位小的移动到右边那个位置。这块的理解可以参考挖坑+ 分治。(http://blog.csdn.net/morewindows/article/details/6684558)。




程序解读

在移动之前,先和标志位比较,首先要定位到比标志位小的数字处(确定比标志位小的 j 的值)while(j>i && a[j]>sig)j--; 这句话有两种退出的情况,第一就是 找到了 j 值使得 a[j] < sig 。还有一种就是 j = i 退出,所以我们接着就是 if(j>i)成立,则是第一种情况,

把a[j] 赋值给 a[i]的值(注意:这就是为什么要把第一个数字取做标志位。)。同时 i++ ,因为现在右边的坑空了,我们需要从左边开始找一个大于标志位的数字放到右边的坑里。i++ 就是确定 第 i 位置的数字已经小于标志位的值,不需要参与比较了。同理从左边开始寻找大于标志位的数字,然后移动过去。最后的状态就是 i 等于 j 。此时把标志位的值赋值给 a[i] 。完成分治的排序。


二 两边分治

如果细细的看“挖坑”的程序,形参 q  和 形参 n 就是 确定的进行挖坑比较的范围,如果你 赋值: q=1;  n=5; 一共有10个待排序的数字,那么程序会把a[q]赋值给sig ,对1--5之内的数字进行挖坑而对于第0个 和 第6--9之间的数字是不会移动的。两边分治的代码就是对两边分别进行挖坑比较。代码如下:


#include<stdio.h>
void quickSort(int a[], int l, int r)
{
    int sig=a[l];
    int i,j;
    i=l;
    j=r;
    if(l<r)  //递归的退出条件
    {
        while(j>i)
        {
            while(j>i && a[j]>=sig)
                j--;
            if(j>i)  
            {
                a[i]=a[j];
                i++;
            }
            while(j>i && a[i]<sig)
                i++;
            if(j>i)
            {
                a[j]=a[i];
                j--;
            }
    }
     a[i]=sig;
     quickSort(a,l,i-1);
     quickSort(a,i+1,r);
    }

}

int main()
{
    int i;
    int a[8]={6,15,9,7,1,8,2,10,};
    quickSort(a,0,7);

    for(i=0;i<8;i++)
        printf("%d ",a[i]);
    return 0;
}


三 快速排序的记忆

 1 先挖坑,挖坑的时候需要定位所以定位代码就是 while 循环,定位到了然后如果比标志值大(或者小)就移动,挖坑完成然后就把标志位移动到最后一个位置。

2再分治,分治的时候就是循环递归的调用,注意递归的退出条件。



 





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值