【昊昊带你学】常见的几种排序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  

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言数组排序函数qsort是标准库函数,用于对数组进行排序。它的使用方法是通过传入一个比较函数来指定排序的规则。在给出的代码中,我们可以看到使用qsort函数对一个整型数组进行升序排序的例子。\[1\] 为了实现qsort函数的功能,我们可以使用一种较为简单的排序算法,比如冒泡排序算法来模拟实现一个具有排序数组、字符串、结构体等功能的bubble_sort函数。\[2\]这个函数的参数可以仿照qsort函数的参数,包括要排序的数组的起始地址、元素个数、每个元素的大小以及一个比较函数。\[3\] 具体实现bubble_sort函数的函数体可以根据冒泡排序算法来编写,通过比较相邻的元素并交换位置来实现排序排序的规则可以通过比较函数来指定,根据需要可以实现升序或降序排序。 总结起来,qsort是C语言标准库中的数组排序函数,可以通过传入比较函数来指定排序规则。如果想要模拟实现类似功能的排序函数,可以使用一种简单的排序算法,比如冒泡排序,并根据需要实现相应的比较函数。 #### 引用[.reference_title] - *1* *2* *3* [【C语言】qsort()函数详解:能给万物排序的神奇函数](https://blog.csdn.net/weixin_72357342/article/details/130628874)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值