排序算法之快速排序,它为什么这么快?

本文将介绍排序算法中最常用,以及最重要的快速排序。

目录

1 快速排序实例

2 代码解析

3 效率分析



1 快速排序实例

快速排序由C. A. R. Hoare在1960年提出,是冒泡排序的一种改进。快速排序就跟它的名字一样,效率很快。跟冒泡排序,选择排序相比,它们使用相同的空间大小,但是,快速排序却可以达到O(nlogn)的时间复杂度,比O(n^2)要快上很多。那么,快速排序是怎么做的呢?它的核心思想是,找到一个基准数,让这个基准数到它该去的位置。并且,基准数左边的数都比这个它要小,右边的数都比它要大。根据这个思想,我们每一趟至少能够保证基准数在它应该在的位置,并且右边的数都大于左边的数,整体基本有序。那怎么处理基准数左边和右边两部分的数呢?很简单,分别对左边和右边递归刚刚那个过程,就ok了。这就是快速排序,由于每次都能够排好一个数,并且能够保证左边区域的数只需要在左边区域排序,右边区域的数只需要在右边区域排序,它们本身在该在位置的概率很大,大大降低了需要交换的次数。

我们来看例子,给定数组[4,5,1,10,3,6,9,2],怎么用快速排序对它排序呢?

首先,选择第一个数作为基准数

设置指针i和j,分别指向最左和最右

扫描二维码关注公众号,回复: 17035083 查看本文章

指针j向左移动,找到第一个小于基准数4的位置。由于指向的2比4小,所以指针j没有移动。

指针i向右移动,找到第一个大于基准数4的位置

交换指针i和j对应的元素

指针j继续向左移动,找到了3比基准数小。

指针i继续向右移动,找到了10比基准数大。

交换指针i和j对应的元素

指针j继续左移,与指针i相遇,停止。

交换指针i与基准数所在位置的元素。

这一趟快速排序结束,基准数4达到了它应该在的位置。而左边都是比4小的数,右边都是比4大的数。接下来我们只需要递归这个过程就可以了。

2 代码解析

49-62行就是刚刚的例子中做的操作,具体在代码注释中已经写明。

66,67行,分别递归处理左边和右边,最终完成整体排序。

这里还有一个问题:为什么每次都要从右边开始找,而不能从左边开始找呢?

如果从左边开始找,那么在这个状态时,i往右一步就停止了。这时候,如果交换基准数和指针i的元素,10会被交换到左边,不符合快速排序“左边的数都比基准数小”的限制。之所以要让指针j先动,就是因为,最后必须停在比基准数小的元素,只有右边先动才可以保证。

3 效率分析

快速排序的效率跟基准数的选择有很大关系。

如果基准数选得好,每次基准数都能够刚好排在中间的位置,递归的时候,两个子问题的大小就是平衡的,不停地二分下去,最终的时间复杂度就是

T(n)=T(n/2)+T(n/2)+O(n)=O(nlogn)

如果基准数选得差,每次基准数刚好是最大值或者最小值,每次子问题的规模只减小了1,这样无疑效率会差很多,最终的时间复杂度为

T(n)=T(n-1)+T(1)+O(n)=O(n^2)

猜你喜欢

转载自blog.csdn.net/Hemk340200600/article/details/104284970
今日推荐