一、简介
快速排序对于初学者而言算是实现较为困难的一种排序方法,而其代码的实现方法也有多种,本文采用其中一种方法实现快排,并采用 主定理 对其复杂度进行分析。
二、基本思想
对于一个已经排序好的数组,一定有该特性:任取一个数字,其左边的数字(若存在)全部小于该数字,其右边的数字(若存在)一定大于该数字。
那么我们便可以对一个未排序数组,任取一个数字(中心数),将小于它的放左边,大于它的放右边,这样就实现了基本的第一步排序。
然后我们对左右两边分别重复以上步骤,直到数组彻底排序。
在快速排序算法中比较重要的一个步骤是找到中心数,一般而言,一个随机的中心数可以使算法更为高效,但为了简便,我们一般取最后一个数字作为中心数。
三、算法实现
import data
nums = data.get_data(1000)
def quick_sort(nums, l, r):
if l < r:
m = partition(nums, l, r)
quick_sort(nums, l, m)
quick_sort(nums, m + 1, r)
# 将数组进行初步划分,小于中心点放左边,大于放右边,返回中心数
def partition(nums, l, r):
m = r - 1 # 取最后一个数作为中心数
i = l # i左边的元素均小于中心数,初始没有
for j in range(i, m):
if nums[j] <= nums[m]:
nums[i], nums[j] = nums[j], nums[i]
i += 1
nums[i], nums[m] = nums[m], nums[i] # 将中心数归位
return i
quick_sort(nums, 0, len(nums))
print(nums)
上面是我采用的一种比较简便的实现方法,这儿有另一个博主写的其他三种方法实现的快速排序,链接:快速排序的三种实现方式以及非递归版本
四、算法分析
主定理
主定理最早出现在《算法导论》中,提供了分治方法带来的递归表达式的渐近复杂度分析。
规模为n的问题通过分治,得到a个规模为n/b的问题,每次递归带来的额外计算为f(n^d)。
即复杂度的表达式可表示为以下形式:
T(n) = aT(n/b) + f(n^d)
那么就可以得到问题的复杂度为:
1、 T(n) = O(n^d log(n)), if a = b^d
2、 T(n) = O(n^d ), if a < b^d
3、 T(n) = O(n^logb(a))), if a > b^d
主定理的证明以及应用举例可参考这篇博文:主定理的证明及应用举例
快速排序算法,我们使用的递归实现,便可用主定理加以分析。
每次问题划分为两个问题,规模减半,带来一次额外的循环,a=2,b=2,d=1,满足上述第一种情况,那么复杂度为n^2 log(n)。