快速排序:
快速排序是对冒泡排序的一种改进。其基本思想基于分治法:在待排序表中选择一个元素当作标准记为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);是一种不稳定的算法。