快速排序——思想和分析

思想

本质上和归并差不多,都是以分而治之的方式来解决问题,将一个大问题划分成相同类型的几个小问题,然后不断递归下去达到问题的最小(每一组只有一个数据)最后将每一个小的排序合在一起,整个数据就是有序的了。

那同样是分治的归并排序,为什么快排就敢叫这个名?(快排应该就是目前排序最快的了)
快排的一个优点就是在合并的时候,不需要再次进行归并,(归并排序中到了合并的环节需要o(n)来将得到的两个子序列合并为有序),而且是原址修改即可。(归并还要单独的数组)

交换

之前提过了可以在原址上进行排序,不需要合并,那么说明肯定分段的时候前面的数据都小于后面的数据,那就需要一个交换的过程了。

交换我们采取的是在片段中选取一个特殊值,来作为交换的依据,而这个值的选择也是有门道的。
书上给了两种方式:

  • ( A[i].key,A[(i+j)/2].key, A[j].key的中值 )
  • 从A[i].key 到 A[j].key 最先找到的两个不同关键字
    中的最大的。
    (上面这些都需要额外写一个函数来求合适的值)

当然了,要是不想选,简单粗暴的选一个片段的第一个或者最后一个元素,不能说不是快排吧。(所以我下面就先拿片段的最后一个元素的值用着)
伪代码:(A为数组名,也没考虑结构体数组什么)

PARTITION(A,p,r)//数组、片段的首尾
x = A[r];//特殊值
i = p-1;
for j = p to r-1
	if A[j] <= x
		i++;
		swap(A[i],A[j]);
swap(A[i+1],A[r]);
return i+1;

实例:A=28713564,传入PARTITION(A,1,len(A))
A[0]不存储,len(A)为元素个数
首先x = 4,i = 0;
第一个元素就需要交换,但是相当于没有交换
然后一直到第四个数据1,要和8交换;
接下来是3,然后结束,得到下面的图片(蓝色标记为i所在的位置)
在这里插入图片描述
然后i+1也就是第四个位置的7和x,也就是最后一个数据4交换,变成:
2134 8567,很好的将大于x和小于x的数据区分开,然后将i+1位置返回,就是割点了。
然后将得到的两个小问题继续递归调用函数,直到每一组只剩下一个元素。

拓展
快排主要是需要选择一个合适的数据,进行粗略的分类然后将大小两部分递归调用函数最后实现排序,当然方法很多种。提过了选择合适数据的几种方式,我们再说一下进行交换的方式:

  • 一个下标从头开始找比特殊值大的数据,另一个从最后开始找比特殊值小的数据,进行交换,然后进行下一组……
  • (i,j)的片段中先存储i的值,设为x,然后从j开始向前找第一个小于x的值,将这个值赋值给i,然后从i向后走,找到第一个大于x的值,存储到j中,然后j继续向前走……最后ij相遇,将x赋值给A[i]即可。

第二种不是很好理解,还是刚才的例子2 8 7 1 3 5 6 4,这次先拿2出来存上。
j从最后开始,第一个比2小的是1,将1放在i的位子上,然后i向后找到8,放在j上……
在这里插入图片描述
最后他们在第二位相遇,将这一位换成存储的x,返回分割点i即可。

分析

快排和归并相比,多了一步交换,但是省下了最后的合并过程,相对于时间上会省。
和归并一样,时间复杂度都是O(nlogn)
【现在才知道我们不写对数的底数不单纯是因为默认为2,是时间复杂度上loga和logb相差只有一个常数(换底公式),完全可以忽略】

每一个子划分需要耗费的时间是O(n),所以我们需要知道树高才能求时间复杂度(当我前面没说是nlogn行吧)

第一种方式下的快排以树的形式写出:(丑了亿点点)
在这里插入图片描述
其实这样还不是很明显,要是这样:
在这里插入图片描述
看起来是不是熟悉了很多?没错就是那个二叉排序树
安利一波之前的博客讲二叉排序树的。

最好情况

都说了看树高,最好的就是平衡二叉树,极端一点就是满二叉树或者完全二叉树,那么树高就是nlogn

最差情况

树高最大,那就是每一个结点都一个孩子:
在这里插入图片描述
那么此时每一层都是n,然后是n层,O(n^2)和基本排序就没什么区别了。
而我们的堆排序和归并排序来说,都能做到上界为o(nlogn),这里快排略显不足。

一般情况来说,快排平均起来还是在O(nlogn)的,并且尾项还是很小的,一般情况还是很快的。

比较排序算法的复杂度下界

和之前的二叉查找树(排序树)差不多,分治策略的排序算法都可以构成一棵树,而基本的交换排序算法在比较的过程中可以实现一个决策树:
在这里插入图片描述
所以我们目前可以知道,分析交换类算法的复杂度下界可以通过考虑树来实现,
并且我们知道每层的代价都是o(n)
所以树高决定下界,最好的树高也就是logn了,所以对于任何基于比较的排序算法,nlogn就是极限了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值