快速排序QuickSort学习

一、基本思想:分割(partition) 用一个数将所有其他数值分成左右两部分,使得左边的数小于等于此数,右边的数都大于等于此数。在寻找的过程中要交换两个数的位置。时间复杂度为O(NlogN),是一种不稳定的排序算法。

二、C++实现代码:

void QuickSort(int a[],int left,int right)
{
	if(left>right)
		return;

	int first=left;
	int last=right;
	int key=a[first];
	while(first<last)
	{
		while(first<last&&a[last]>=key)
			--last;
		a[first]=a[last];
		/*将比第一个大的移到高端*/
		while(first<last&&a[first]<=key)
			++first;
		a[last]=a[first];
		/*将比第一个大的移到高端*/
		a[first]=key;
		/*将比第一个大的移到高端*/
		QuickSort(a,left,first-1);
		QuickSort(a,first+1,right);
	}
}

一趟快速排序的算法是:

1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;

2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];

3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]的值赋给A[i];

4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]的值赋给A[j];

5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。

三、在C++中使用:

sort(buf, buf+n, cmp);

  1. 1)buf:待排序数组的首地址,待排序数组元素共n个。
  2. 2)buf+n:此处是重点,这个参数不是待排序数组的最后一个元素的地址,而是最后一个元素的后地址。简单来讲,可以理解为 [buf, buf+n) ,即这里两个参数表示的意义是左闭右开。
  3. 3)cmp:排序方法,这个参数可以省略,省略后默认从小到大排序。也可以自己写一个比较函数来实现,具体见下面的例子。
#include <algorithm>
using namespace std;


bool cmp_up(int a,int b)//升序排序
{
    return a<b;
}
 
bool cmp_down(int a,int b)//降序排序
{
    return a>b;

int main()
{

    int a[6]={2,9,8,4,6,7};
    sort(a,a+6);
    //调用方法
    sort(a,a+6,cmp_up);
    sort(a,a+6,cmp_down);

    return 0;
}
//sort(buf, buf+n, cmp);

四、寻找第k小值数字: 

(1) 当规模小于阈值时,直接用排序算法返回结果。

(2) 当n大于阈值时,把n个元素划分为5个元素一组的n/5组,排除剩余元素(不会有影响,这里只是为了求中项mm),分别排序,然后挑出每一组元素的中间值,再在所有的中间值中,递归调用本算法,挑出中间值mm。

(3) 把元素划分为A1、A2、A3三组,分别包含小于、等于、大于mm的元素。

(4)分三种情况:

若A1的元素数量大于等于K,即第K个元素在第一组内:在A1中递归查找第k小元素。

若A1、A2元素个数之和大于等于K,即中项mm为第K个元素:返回mm

否则,第K个元素在第三组:在A3中递归寻找第(k-|A1、A2元素数量之和|)小元素。

int findLastKMinNum(int A[],int low,int high,int k)
{
	//设置阈值
	int p=high-low+1;
	if(p<6){
		sort(A,A+p);
		return A[k-1];
	}
	else{
		//分为五段
		int q=p/5;
		int remainder=p-q*5;
		//每段排序并把中项放入mid
		int *mid=new int[q+1];
		for(int i=0;i<q;i++)
		{
			sort(A[5*i],A[5*(i+1)]);
			mid[i]=A[i*5+2];
		}
		if(remainder>0){
			sort(A[5*q],A[5*q+remainder]);
			mid[q]=A[q*5+(remainder+1)/2-1];
		}
		//中项集合的中项
		int mm=findLastKMinNum(mid,0,q-1,(q+1)/2);
		int *A1=new int[p];
		int *A2=new int[p];
		int *A3=new int[p];
		int lenA1=0,lenA2=0,lenA3=0;
		//分别与中项比较,分为新的三段
		for(int i=low;i<=high;i++){
			if(A[i]<mm)
				A1[lenA1++]=A[i];
			else if(A[i]==mm)
				A2[lenA2++]=A[i];
			else if(A[i]>mm)
				A3[lenA3++]=A[i];
		}
		//将三段的长度与k比较判断k的位置并递归
		int lastKMin=0;
		if(lenA1>=k)
			lastKMin=findLastKMinNum(A1,0,lenA1-1,k);
		else if(lenA1+lenA2>=k)
			lastKMin=mm;
		else if(lenA1+lenA2<k)
			lastKMin=findLastKMinNum(A3,0,lenA3-1,k-lenA1-lenA2);
		delete[] mid;

		return lastKMin;
	}

}

参考:

三种解法:https://blog.csdn.net/weixin_37922777/article/details/82666466

猜你喜欢

转载自blog.csdn.net/wxq_1993/article/details/86613888