快速排序+优化

快速排序:

        快速排序是对冒泡排序的一种改进。其基本思想基于分治法:在待排序表中选择一个元素当作标准记为Mark,通过一次排序将排序表分成两个部分,前一部分是小于Mark的所有元素,后一部分是大于等于Mark,Mark放在了最终的位置上,这一过程叫做一趟快速排序。然后分别递归的对两个子表进行上述重复过程,直到每个部分内只有一个元素或者是空为止,最后所有的元素都放在了它最终的位置上。


快速排序的过程:

1.小区间扩张法:

        首先找到一个标准(数组中最后一位),然后设定小区域,即(所有小于标准的元素都排在小区域内)。当遇到元素比标准小时,元素交换,小区域扩大;当遇到元素与标记相等时,不换,元素继续向下寻找;当元素大于标准时,不换,元素继续向下寻找。

代码:
#include<iostream>
using namespace std;
int QSort(int arr[],int nLow,int nHigh)
{//标准值为arr[nHigh];
	int nSmall;
	nSmall = nLow-1;//划分小区域小区域在起始点的前一位
	for(nLow;nLow<nHigh;nLow++)
	{
		//当前值比标准值小 
		if(arr[nLow]< arr[nHigh])
		{
			//小区间扩张 交换
			if(++nSmall != nLow)
			{
				arr[nSmall] = arr[nSmall]^arr[nLow];
				arr[nLow] = arr[nSmall]^arr[nLow];
				arr[nSmall] = arr[nSmall]^arr[nLow];
			}
		}
	}
//当标准值把数组arr分成了两部分以后(前一部分小于标准值,后一部分大于标准值),将标准值与小区间前的一位元素进行互换,
	//标准值放入
	if(++nSmall != nHigh)
	{
		arr[nSmall] = arr[nSmall]^arr[nHigh];
		arr[nHigh] = arr[nSmall]^arr[nHigh];
		arr[nSmall] = arr[nSmall]^arr[nHigh];
	}
	//返回标准值位置
	return nSmall;
}
优化方法:

        1.标准的选择:

        ①:标准可以不再是单纯的选择最后以为定位标准,可以使用中位数法来确定标准数,即:

     int M = arr[low]+(arr[high]-arr[low])/2;//生成中间数
     int p = (arr[low]+arr[high]+arr[M])/3;//生成中位数

        ②:标准的选取可以使用随机数生成发生成。

     srand((unsigned)time(NULL));  //生成随机数
     int p = rand()%(high - low) + low;//随机生成标准,在high到low之间

        2.使用插入排序替换快速排序

        假设待排序长度为M,若(high-low+1<M)成立时,使用插入排序。

if (high - low + 1 < 10)  
{  
    InsertSort(arr,low,high);  
    return;  
}//else时,正常执行快排 
        3.将数组分成三部分,前端小于标准值,中部等于标准值,后部大于标准值。(类似与荷兰国旗问题。)
void QSort(int arr[],int l,int h)//最后一位时划分值,用l变量遍历所有数组,arr[l]为当前数,l++
{       int p = arr[h];//标准值
	int less = l-1;//小区间
	int more = h;//大区间
	while(l<more)
	{
		if(arr[l]<p)
		{
			swap(arr,++less,l++);//将小区域的下一个与当前数字交换,扩大小区域,交换后l++,
		}
		else if(arr[l] == p)
		{
			l++;//当前数字等于划分之 仅仅时当前位置l++
		}
		else
		{
			swap(arr--,--more,l);//当前值大于标准值,交换当前值与大区间的后一个,扩大大区间,当前位置不变
		}
	}
}
复杂度与稳定性:

        快速排序最优时间复杂度时O(nlogn);最差时间复杂度时O(n^2);平均时间复杂度时O(nlogn);空间复杂度最差是O(n);最优空间复杂度是O(logn);是一种不稳定的算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值