快速排序是在实际中最常用的一种排序算法,速度快,效率高。就像名字一样,快速排序是最优秀的一种排序算法。
思想 快速排序采用的思想是分治思想。Portition
快速排序是找出一个元素(理论上可以随便找一个)作为基准(pivot),然后对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值 都不小于基准值,
如此作为基准的元素调整到排序后的正确位置。
递归快速排序,将其他n-1 个元素也调整到排序后的正确位置。最后每个元素都是在排序后的正确位置,排序完成。
所以快速排序算法的核心算法是分区操作,即如何调整基准的位置以及调整返回基准的最终位置以便分治递归.
#include <iostream>
using namespace std;
int Portition(int a[], int low, int high)
{
int temp = a[low];
while(low<high)
{
while(low<high && a[high]>=temp)
{
high--;
}
int aa = a[low];
a[low] = a[high];
a[high] = aa;
while(low<high && a[low]<= temp)
{
low++;
}
aa = a[low];
a[low] = a[high];
a[high] = aa;
}
return low;
}
void QSort(int a[], int low, int high)
{
if(low<high)
{
int temp =Portition(a, low, high) ;
QSort(a,low,temp-1);
QSort(a,temp+1,high);
}
}
void QuickSort(int a[], int n)
{
QSort(a, 0, n-1);
}
int main()
{
int a[9]={5,1,9,3,7,4,8,6,2};
cout<<"before sort:";
for(int i=0;i<9;i++)
{
cout<<a[i]<<" ";
}
cout<<endl; QuickSort(a,9); //nlogn no
cout<<"after sort:";
for(int i=0;i<9;i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
return 0;
}
关于快速排序的优化
1. 优化选取的枢轴尽量将我们选取的数值 为中间点
int Portition(int a[],int low, int high)
{
if(a[low]>a[high])//优化选取的枢纽
{
swap(a,low,high)//low high 数值交换
}
if(a[mid]>a[high])
{
swap(a,mid,high)//mid high 数值交换
}
if(a[mid]>a[low])
{
swap(a,mid,low)//mid low 数值交换
}
int temp = a[low];
while(low<high)
{
while(low<high && a[high]>=temp)
{
high--;
}
int aa = a[low];
a[low] = a[high];
a[high] = aa;
while(low<high && a[low]<= temp)
{
low++;
}
aa = a[low];
a[low] = a[high];
a[high] = aa;
}
return low;
}
2. 优化在Protition 程序中不必要的 交换
int Portition(int a[], int low, int high)
{
while(low<high)
{
while(low<high && a[high]>=temp)
{
high--;
}
a[low] = a[high];//优化
while(low<high && a[low]<= temp)
{
low++;
}
a[high] = a[low]// 优化
}
a[low] = temp;//将temp 移动到最终目标位置
return low;
}
3.优化小数组时候的排序方法 由于快排用到了递归因此 会有大量的函数调用,在处理小数据量排序时反而不如简单排序好。
意思就是说我可以在前半段用递归QSort处理大于7,后面用InsertSort 处理小型排序
#define MAX_Length_insertSort 7 或者 50
void QSort(int a[], int low, int high)
{
if(high-low > MAX_Length_insertSort)
{
int temp =Portition(a, low, high);
QSort(a,low,temp-1);
QSort(a,temp+1,high);
}
else
{
ISort(a+low, high-low+1);
//调用 直接插入就好了
}
}
void ISort(int a[], int n)
{
//原来直接插入排序的内容
for(int i=1;i<n;i++)
{
if(a[i]<a[i-1])
{
int temp = a[i];
int j = i-1;
for(;j>=0 && temp<a[j];j--)
{
a[j+1] = a[j];
}
a[j+1]=temp;
}
}
}
4. 优化递归操作 ,采用迭代 不是递归就缩减了堆栈的深度 函数循环调用的程度。 提高性能
快排函数在函数尾部有两次递归操作,我们可以对其使用尾递归优化
优点:if变成while 循环后第一次 QSort(a,low,temp-1)循环以后 变量low没用了
这时候我们将temp+1赋值给low 在while满足时执行Portition(a, low, high) 效果等效与QSort(a,temp+1,high);
void QSort(int a[], int low, int high)
{
while(low<high)
{
int temp =Portition(a, low, high) ;
QSort(a,low,temp-1);
// QSort(a,temp+1,high);=>low =temp+1;
low =temp+1;
}
}
while (low < high)
{
pivot = Partition(list,low,high);
if (pivot - low < high - pivot)
{
quicksort(list,low,pivot - 1);
low = pivot + 1;
}
else
{
quicksort(list,pivot + 1,high);
high = pivot - 1;
}
}
优化5:在一次分割结束后,可以把与Key相等的元素聚在一起,继续下次分割时,不用再对与key相等元素分割
http://blog.csdn.net/hacker00011000/article/details/52176100
概括:这里效率最好的快排组合 是:三数取中+插排+聚集相等元素,它和STL中的Sort函数效率差不多
注意:由于测试数据不稳定,数据也仅仅反应大概的情况。如果时间上没有成倍的增加或减少,仅仅有小额变化的话,我们可以看成时间差不多.