Partition函数实现的快速排序和寻找第k大数

本文深入探讨了快速排序的核心——Partition函数,详细解释了其工作原理,并展示了如何利用该函数实现快速排序及寻找数组中第k大数的算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Partition函数实现的快速排序和寻找第k大数

快速排序的核心内容其实就是Partition函数,以前一直没有什么深入的理解,也只是背一下快排的代码,再后来干脆直接用sort了。但是了解Partition函数对于理解快排非常重要,还可以实现别的应用。

Partition函数的功能:对于一个你选定的数,将小于这个数的元素放置到数组的一边,大于这个数的元素放置到数组的另一边,最后你可以知道这个选定的数在数组中是第几大的。

下面给出一个样例的Partition函数:

int Partition(int A[], int Left, int Right){
	int Pivot = A[Left] ;
	int L = Left, R = Right ;
	while( L < R ){  
		while( A[R] < Pivot && L < R ) R-- ;
		while( A[L] >= Pivot && L < R ) L++ ; 
		Swap( A[L], A[R] ) ;
	}
	Swap( A[Left], A[R] ) ; 
	return L ;
} 

可以看到,这个Partition函数选择了最左边的元素作为主元(比较的标杆),把小于等于主元的数放到了右边,大于等于主元的数放到了左边。注意,这里有一个小陷阱:因为最后要进行Swap( A[Left], A[R] ),这意味着最后的A[R]一定是一个大于等于主元的数。所以,我们把R的while循环写到前面。如果循环因为A[R]>Pivot而停止,那么是合法的;如果因为R==L而停止,可以想一下,交换过后A[L]总是大于等于Pivot,所以也是合法的。

这样的话,一次Partition就把数组分成了两个部分。这样再递归处理左右两边就可以完成快速排序了。

PivotPivotPivot 的选择是很关键的,决定了你划分的好坏。一般的方法是选择左,中,右三个元素的中间值。

void Quicksort(int A[], int Left, int Right ){
	if( Left >= Right ) return ;
	int index = Partition(A, Left, Right ) ;
	Quicksort(A, Left, index-1 ) ;
	Quicksort(A, index+1, Right ) ; 
}

即使不谈快速排序,Partition函数依然很有用:可以寻找乱序数组中的第k大数。能不能想到怎么做呢?

前面说过,Partition函数可以返回主元在数组段中的大小位置。如果我们要寻找的元素是第k大的,而当前的Partition返回的值是m(按照给出样例中的Partition函数讨论),则:

  1. k == m 恭喜你,这个元素正是你需要的!
  2. k < m 说明要找的数比这个数大,也就是说,在这个数的左边
  3. k > m 说明要找的数比这个数小,也就是说,在这个数的右边

如此一来,问题就被一次Partition函数分解了。只需要向下递归几次,就可以找到想要的数。

int findk(int A[], int Left, int Right, int k ) {
	int index = Partition(A, Left, Right ) ;
	if( index == k-1 ) return A[index] ;
	else if( index < k-1 ) return findk(A, index+1, Right, k) ;
	else return findk(A, Left, index-1, k) ;
}

由于其递归的特性,代码写起来也比较简洁明了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值