快速排序

概念引入

快速排序顾名思义就是比较快速的排序(好吧的确是废话)
快速排序的主要实现原理其实是分治(如果不知道分治是啥的小朋友可以近似的理解为低配版二分)
选定一个基准 然后将比基准小的数都放在基准左边 比基准大的数都放在基准右边 (基准的位置确定了)
然后分别对基准左边的序列和基准右边的序列进行快速排序(分治)直到整个序列有序
平均情况下需要(log_n)轮 所以时间平均复杂度应该是(nlog_n) 但是如果我们每次恰好选定的基准选到了最大值(那你可真是倒霉) 那我们每次只能确定基准一个在最终序列中的位置, 最终的时间复杂度仍然是(n^2)
关于如何选择基准和如何移动数字 我们会在下面的章节中讲到

基准的选择

一般来说可以随机选择基准:选择序列的最左边或者最右边都行 ,但是刚才我们已经分析过最差的时间复杂度会是(n^2),如果出题人丧心病狂的让你把一个完全逆序的序列排成一个升序,那我们只能(n^2)了,所以我们一般会随机选取一个数
如果是用随机函数的话,又太过麻烦,如果用一个自己写的函数去选,又可能会影响到快排的效率(快排是(nlog_n)结果你写了一个(n^3)的随机选数 那宁可真是个小机灵鬼
这里提供一种方法叫做三数中值法,即选择序列中间的数,最左边的数,最右边的数,然后取三个数的平均数来作为基准(如果出题人心理正常的话应该就不会卡你了

算法实现

主要的实现方法有两种: 挖坑法和指针法 一般来说指针法使用较为广泛
首先来看挖坑法:

  • 现在给定一个序列a[] = 4,7,6,5,3,2,8,1 要求将其按升序排序
  • 现在来整个图

    首先,我们选定基准元素Pivot,并记住这个位置index,这个位置相当于一个“坑”。并且设置两个指针left和right,指向数列的最左和最右两个元素:

    接下来,从right指针开始,把指针所指向的元素和基准元素做比较。如果比pivot大,则right指针向左移动;如果比pivot小,则把right所指向的元素填入坑中。

在当前数列中,1<4,所以把1填入基准元素所在位置,也就是坑的位置。这时候,元素1本来所在的位置成为了新的坑。同时,left向右移动一位。

此时,left左边绿色的区域代表着小于基准元素的区域。

接下来,我们切换到left指针进行比较。如果left指向的元素小于pivot,则left指针向右移动;如果元素大于pivot,则把left指向的元素填入坑中。

在当前数列中,7>4,所以把7填入index的位置。这时候元素7本来的位置成为了新的坑。同时,right向左移动一位。

此时,right右边橙色的区域代表着大于基准元素的区域。

下面按照刚才的思路继续排序:

8>4,元素位置不变,right左移

2<4,用2来填坑,left右移,切换到left。

6>4,用6来填坑,right左移,切换到right。

3<4,用3来填坑,left右移,切换到left。

5>4,用5来填坑,right右移。这时候left和right重合在了同一位置。

这时候,把之前的pivot元素,也就是4放到index的位置。此时数列左边的元素都小于4,数列右边的元素都大于4,这一轮交换终告结束。

  • 指针法:
    仍然是刚才的序列a[] = 4,7,6,5,3,2,8,1 要求将其按升序排序

开局和挖坑法相似,我们首先选定基准元素Pivot,并且设置两个指针left和right,指向数列的最左和最右两个元素:

接下来是第一次循环,从right指针开始,把指针所指向的元素和基准元素做比较。如果大于等于pivot,则指针向左移动;如果小于pivot,则right指针停止移动,切换到left指针。

在当前数列中,1<4,所以right直接停止移动,换到left指针,进行下一步行动。

轮到left指针行动,把指针所指向的元素和基准元素做比较。如果小于等于pivot,则指针向右移动;如果大于pivot,则left指针停止移动。

由于left一开始指向的是基准元素,判断肯定相等,所以left右移一位。

由于7 > 4,left指针在元素7的位置停下。这时候,我们让left和right指向的元素进行交换。

接下来,我们进入第二次循环,重新切换到right向左移动。right先移动到8,8>2,继续左移。由于2<8,停止在2的位置。

切换到left,6>4,停止在6的位置。

元素6和2交换。

进入第三次循环,right移动到元素3停止,left移动到元素5停止。

元素5和3交换。

进入第四次循环,right移动到元素3停止,这时候请注意,left和right指针已经重合在了一起。

当left和right指针重合之时,我们让pivot元素和left与right重合点的元素进行交换。此时数列左边的元素都小于4,数列右边的元素都大于4,这一轮交换终告结束。

以上就是快速排序的一般思路 (sort大法好) 虽然现在有现成的sort可以用但是快排的思想还是要掌握的

点个关注>.)<

以上插图及过程参考博客

如初见 与初见
原文地址:https://www.cnblogs.com/HISKrrr/p/13257609.html