04算法-快速排序(深入分析)

abstract

本文是对快速排序算法的深入分析,主要讲解了快速排序算法的基本原理,时间复杂度分析以及如何去改进的快排算法,本文提供快排的伪代码,以及用Golang实现的具体代码。
这里补充一下一般算法设计的思路,首先根据问题分析建模,设计最初版本的代码,分析代码的running time,然后找到问题所在,解决问题。这样的。

the idea of algorithm

快速排序算法是典型的使用分治法设计的算法,算法主要分为:
dividekey这是快排的关键,
conquer:recursive sort 2 part
combine:这部分不做什么,因为快排不像merge sort没有消耗而外的空间
实现快排的关键就是在线性的时间,完成对子数组的分割

common quick sorting

我们先开快排的伪代码

//其中分割函数
partition(A, p, q)
	X <- A[p]  
	curr <- p
	for j <- p+1 to q
		do if A[j] <= X 
			then curr <- curr+1
				exch A[curr] A[j]
	exch A[p] A[curr]
	return curr

//对于combine部分
quickSort(A, p, q)
	if p < q then
		mid <- partion(A, p, q)
		quickSort(A, p, mid-1)
		quickSort(A, mid+1, q)

使用GO实现的代码如图所示:

func partition(A []int, left, right int)  int{
	midNum := A[left]
	startFLag := left
	for i := left+1; i <=right; i++{
		if A[i] <= midNum{
			startFLag++
			A[i], A[startFLag] = A[startFLag], A[i]
		}
	}
	A[left], A[startFLag] = A[startFLag], A[left]
	return startFLag
}

func QuickSort(A []int, left

 - [ ] List item

, right int)  {
	if right > left{
		mid := partition(A, left, right)
		QuickSort(A, left, mid-1)
		QuickSort(A, mid+1, right)
	}
}
下面说一下时间复杂度

上述算法的运行时间是取决于输入数据的情况
我们来考虑==最好的情况(卵用没有)==假设每次选择的数据都会置换到当前数据段的中心,那递归公式为 T ( n ) = 2 T ( n / 2 ) + Θ ( n ) T(n)= 2T(n/2)+\Theta(n) T(n)=2T(n/2)+Θ(n) 所以其running time为 Θ ( n l g n ) \Theta(nlgn) Θ(nlgn)
我们考虑最坏的情况,每次置换过后的位置都是 l e f t + 1 left+1 left+1,那递归公式就是 T ( n ) = T ( 0 ) + T ( n − 1 ) + Θ ( n ) T(n)=T(0)+T(n-1)+\Theta(n) T(n)=T(0)+T(n1)+Θ(n)所以其running time为 Θ ( n 2 ) \Theta(n^2) Θ(n2)
对于一个普通的情况,一般会偏向于好的情况一点,但是这种程度的算法是达不到实际使用需求的。

rand quick sorting

考虑到上面的问题,我们需要改进快速排序算法,其中最容易想到的是:将挑选的元素随机话。

func randPartition(A []int, left, right int)  int{
	key := int(rand.Int63n(int64(right-left))) + left
	A[left], A[key] = A[key], A[left]

	midNum := A[left]
	startFLag := left
	for i := left+1; i <=right; i++{
		if A[i] <= midNum{
			startFLag++
			A[i], A[startFLag] = A[startFLag], A[i]
		}
	}
	A[left], A[startFLag] = A[startFLag], A[left]
	return startFLag
}

其中随机话处理的代码如上所示。这样处理能够带来什么样的好处了。这样能保证算法的 r u n n i n g   t i m e < = a n l g n running\ time <= anlgn running time<=anlgn
下面是纯数学分析,如果不想了解太深,完全没有必要看
在证明上面的结论上,需要使用到一个定律 ∑ k = 2 n − 1 k l g k < = 1 2 n 2 l g n − 1 8 n 2 \sum_{k=2}^{n-1}klgk<={\frac 12}n^2lgn-{\frac 18}n^2 k=2n1klgk<=21n2lgn81n2
首先定义了一个这样的概率分布函数 x k = 1 ( i f   t h e r e   i s   a   p a r t i t i o n   k : n − k − 1 )   a n d   x k = 0 ( o t h e r ) x_k=1(if\ there\ is\ a\ partition\ k:n-k-1)\ and\ x_k = 0(other) xk=1(if there is a partition k:nk1) and xk=0(other)
对于T(n)这个函数,它的表现形式就可以写成 T ( n ) = ∑ k = 2 n − 1 x k { T ( k ) + T ( n − k − 1 ) + Θ ( n ) } T(n)=\sum_{k=2}^{n-1}{x_k\{T(k)+T(n-k-1)+\Theta(n)\}} T(n)=k=2n1xk{T(k)+T(nk1)+Θ(n)}式中可以不考虑k=0和1的情况。
根据独立分布的特性可以推导为 E ( T ( n ) ) = 2 n ∑ k = 2 n − 1 { T ( k ) + Θ ( n ) } E(T(n))={\frac 2n}\sum_{k=2}^{n-1}{\{T(k)+\Theta(n)\}} E(T(n))=n2k=2n1{T(k)+Θ(n)}
E ( T ( n ) ) = 2 n ∑ k = 2 n − 1 T ( k ) + Θ ( n ) E(T(n))={\frac 2n}\sum_{k=2}^{n-1}T(k)+\Theta(n) E(T(n))=n2k=2n1T(k)+Θ(n)
再用代换法加上上面给出的定理来证明:
假设 < = 2 n ∑ k = 2 n − 1 a k l g k + Θ ( n ) <={\frac 2n}\sum_{k=2}^{n-1}aklgk+\Theta(n) <=n2k=2n1aklgk+Θ(n)
< = 2 a n ( 1 2 n 2 l g n − 1 8 n 2 ) + Θ ( n ) <={\frac {2a}n}({\frac 12}n^2lgn-{\frac 18}n^2)+\Theta(n) <=n2a(21n2lgn81n2)+Θ(n)
< = a n l g n − a 4 n + Θ ( n ) <=anlgn -{\frac a4}n+\Theta(n) <=anlgn4an+Θ(n)
so when a 4 n > Θ ( n ) {\frac a4}n>\Theta(n) 4an>Θ(n), the next is proved
< = a n l g n <=anlgn <=anlgn

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值