【昊昊带你学】常见的几种排序2(qsort)

**************************转载请注明出处!******************************

         Qsort快排,顾名思义,它是排序算法,而且它快,是吧。那这个快从何说起呢?写到这我才发现,说前面几个算法的时候,对时效只字未提,0.0 证明昊昊的确是灰常不合格的程序猿。插入,选择,冒泡,bla bla~我们把它们看做O(n^2)的算法,这里的这个O是个渐进记号,表示的是渐进上界,当然还有一种Θ,它同时渐进地给出了函数的上界及下界。严谨的判断方法当然应该讲算法运行步数表示成一个跟输入规模n有关的函数。当然,精确地计算看起来很麻烦,当n→∞时,许多项可以忽略,再把系数啥的忽略了,就得到上面的O()了(好像是这么回事,这就是我当初在概论里没说这事儿的原因,我自己也不是啥细节都清楚)。而Qsort的效率就要高很多,平均O(nlogn)。不随机的情况下,最坏情况貌似也是O(n^2)。下面就进入正题:qsort!

基本描述

         首先要说的是,快排也是基于分治思想的。它分为几个步骤,首先对要排序数组划分(先找出一个pivot(不知道该肿么翻,总之是用来作为比较的标准),将比pivot小的挪到pivot的一侧,其他到pivot的另一侧)。然后再递归地用qsort来排序pivot两边的数组。边界可以设成一个数、两个数,也可以设成小于某个量的时候该用插入排序之类的,它们开销比较小,在小规模的时候不逊于快排。

实现

         我们把分划的那一步单独拿出来,称作PARTITION(A, p, r),它返回的是pivot的坐标。假设我们已经完成了这个函数,我们来看一看快排要怎样完成工作,伪代码如下:

         QUICKSORT(A, p, r)

                   If p<r

                            Then q ← PARTITION(A, p, r)

                                     QUICKSORT(A, p, q-1)

                                     QUICKSORT(A, q+1, r)

         看起来好简洁是么,bingo~qsort本来就不是很难,只是好多同学刚开始学的时候,没有很好的接受递归、分治的思想,接受之后这些都是理所当然了哈~仔细来看一下。上面这个伪代码对边界没有特别处理,指针交叉了就完事儿。在工作时(p为左边界,r为又边界),分划过后,q得到pivot的位置。此时数组的情况是,q左边的都小于pivot,q右边的都大于pivot(假设从小到大)。排序p到r数组的问题,就成功的被分解成了排序p到q-1数组以及排序q+1到r数组。不断分划,数组长度越来越短,当p == r时,q == p == r。那么再向下调用QUICKSORT()时就停止了。循环不变的证明就不抄了,我自己是写不出来那么严谨的证明,详细证明大家可以google之类的查查资料吧。

 

         接下来就是算法中关键的部分,PARTITION分划!伪代码如下:

PARTITION1(A, p, r)

                   X ← A[r]

                   I ← p-1

                   For j ← p to r-1

                            Do if A[j] <= x

                                     Then i ← i+1

                                               Exchange A[i] ↔ A[j]

                   Exchange A[i+1] ↔ A[r]

                   Return i+1

         注意这是PARTITION1,我常用的不是这个,不过既然《导论》先介绍它,我也把它放到前面来说吧。上来两个变量,X I。X作为pivot使用,而i则是分界线,从左向右扫。工作时,j左侧是已经分划的一部分,其中i左侧的数小于X,当j扫到r-1时,i左侧都小于X,所以将A[i+1] 与 A[r]交换,此时,就分划完成了。同样,这不是严格的循环不变式证明,只是大体有个框框,说明一下这个分划的正确性。

         PARTITION2(A, p, r)

                   X ← A[p]

                   I ← p-1

                  J ← r+1

                   Whie TRUE

                            Do   repeat j ← j – 1

                                               Until A[j] <= x

                                     Repeat I ← I + 1

                                               Until a[i] >= x

                                     If I < j

                                               Then exchange A[i] ↔ A[j]

                                               Else return j

         这好像也是最初的那个版本0.0。首先X是pivot,毫无疑问。然后左右指针分别是I j。左右指针分别向中间扫,j扫到一个小于等于X的停下,i扫到一个大于等于X的停下。俩指针交换一下继续,知道指针交叉,返回j。

举例(PARTITION1)

1)        2   8   7   1   3   5   6  |4

        I p,j                              r

 

2)        2|  8   7   1   3   5   6  |4

          I,p  j                           r

 

3)        2|  8|  7   1   3   5   6  |4

          I,p       j                      r

 

4)        2|  8   7|  1   3   5   6  |4

          I,p            j                 r

 

5)        2   1|  7   8|  3   5   6  |4

          p    i              j             r

 

6)        2   1   3|  8   7|  5   6  |4

          p         i              j        r

 

7)        2   1   3|  8   7   5|  6  |4

          p         i                  j    r

 

8)        2   1   3|  8   7   5   6|  4

          p         i                       r

 

9)        2   1   3|  4|  7   5   6   8

          p         i                       r

         好吧,我只能尽力做成这样了0.0我觉得大家应该能看懂吧。每个步骤包含两行,第一行是当前数组状态,第二行是各个指针状态。”|”将数组分割成若干段。最右边的”|”表示j只能扫到6,而不会扫到最右的数。然后最左面的”|”跟着i,意味着它左边的数都小于4。中间的”|”跟着j,就是说它左边的都已经分划好了。9)处,4已经找到正确位置,左”|”的左侧都小于4,右”|”的右侧都大于4。此时就可以返回i+1了,正好是4(pivot)的位置。

 

         快排应该算是一个非常重要的算法,估计咱们考试也会考到吧~大家还是自己亲手敲一敲代码体会体会吧。哈哈~

http://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html  

之前提到过的,这里有可视化的快排。

主页里分享了形象的快排视频。大家可以去看一下,主页菌感觉非常棒。

新学期开始了,主页菌祝大家算法数据结构能那个好成绩,嘎嘎~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值