初级算法:快速排序

如果对快速排列不是很懂得话个人建议在看该博客时可以在纸上演算,这样更便于理解。

在学快速排序前要先学会函数调用和递归。因为这是学习该算法的基础,特别是递归(个人建议学习递归时最好找一个简单一点的递归类型的题进行练习,并且在纸上将递归的每一步都写下来这样有助于对递归更好的理解)。

快速排序所采用的思想是分治的思想。所谓分治,就是指以一个数为基准假设该数为A,将序列中的其他数往它两边“扔”。以从小到大排序为例,比它小的都“扔”到它的左边,比它大的都“扔”到它的右边,然后左右两边再分别重复这个操作,不停地分,直至分到每一个分区的基准数的左边或者右边都只剩一个数为止。这时排序也就完成了。

在快速排序中的确定所谓的基数后记下该基数的位置(切记是位置而不是该位置里面存放的数字A),然后以该位置为标点将该列数分为两部分,如上段所举的例子,按从小到大排列,则该标点的的左边为小于A的数,右边为大于A的数。此时左右两部分中的数字为无序的。此时可以将左右两段看成是独立的两部分然后再按照上述同样的操作进行排序,最后就可以得到一个从小到大排列的数据。

该算法可以看成是挖坑+填坑+分治的结合,这样比较容易理解。

以下为一具体实例的步骤,以表格的形式体现。

给出一个大小为10的数组数组中的数为下表

0123456789
7265788604283734885

初始时 i=0,j=9,x=a[0]=72;

此时可以视为将a[0]中的数已经被取出,即a[0]已经挖坑完成,则会出现下表

0123456789
 65788604283734885

此时将x与a[j]进行比较若x<a[j]则j--。如果x>a[j]则a[i]=a[j],i++。此时a[i]中的坑已经被填上,而a[j]被挖坑了。具体实例为

x<a[9] , j--。x>a[8] , a[0]=a[8] , i++;此时x的值不改变

可以得出下表

0123456789
486578860428373 85

因为右边出现了空所以这次需要找右边的数去将右边的空填满,所以

此时若x>a[i] , i++ 如果 x<a[i] , a[j]=a[i] , j--;具体实例为

x>a[1] , i++。x>a[2] , i++。x<a[3] , a[8]=a[3] , j--

可得下表

0123456789
48657 604283738885

 以此类推直到i>=j为止

此时的表格中的数为

0123456789
4865742607283738885

此时的表格中a[6]=72的左边全为小于72的数右边为大于72的数(两部分的数并不是有序的)

此时要将左右两部分看成是单独的两部分,并重复上述的操作便可以得到从小到大的有序数列,如下表

0123456789
6424857607273838588

对挖坑填数进行总结:

    • 1.i =L; j = R; 将基准数挖出形成第一个坑a[i]。
    • 2.j--由后向前找比它小的数,找到后挖出此数填前一个坑a[i]中。
    • 3.i++由前向后找比它大的数,找到后也挖出此数填到前一个坑a[j]中。
    • 4.再重复执行2,3二步,直到i==j,将基准数填入a[i]中。

具体代码如下:

void quick_sort(int s[], int l, int r)

{

    if (l < r)

    {

        //Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 

        int i = l, j = r, x = s[l];

        while (i < j)

        {

            while(i < j && s[j] >= x) // 从右向左找第一个小于x的数

                j--;

            if(i < j)

            {

                s[i] = s[j];

                i++;

            }

            while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数

                i++;

            if(i < j)

            {

                s[j] = s[i];

                j--;a

            }

        }

        s[i] = x;

        quick_sort(s, l, i - 1); // 递归调用

        quick_sort(s, i + 1, r);

    }

}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值