什么是快速排序?
顾名思义,快速派速是一种速度比较快,即时间复杂度较低的一种排序方法,其适用于数据混乱无章的情况,在数据完全有序的情况下,快速排序比较糟糕。
算法思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小;然后再次按照本方法对两部分再次排序,通过递归;最后数据全部有序。
C代码:
int partition(int a[] ,int low,int high) //一次快速排序
{
int key=a[low];
while(low<high)
{
while(low<high && a[high]>key) high--;
if(low<high) a[low]=a[high];
while(low<high && a[low]<=key) low++;
if(low<high) a[high]=a[low];
}
a[low]=key;
return low;
}
void swap(int &a,int &b) //交换函数
{
int tmp=a;
a=b;
b=tmp;
}
void QuickSort(int a[] ,int low,int high) //简单快速排序
{
if(low>=high)
{
return;
}
int index=partition(a,low,high);
QuickSort(a,low,index-1);
QuickSort(a,index+1,high);
}
上面的快速排序算法选取第一个元素为主元(即key),以此为依据将数据划分为两部分,但如果数据是完全有序的,那么此时时间复杂度为O(n^2),所以要采取优化。
C代码(优化一):采取三取样中值法,即在要排序的数组中,选取第一个数据 最后一个数据 以及中间的数据 取这三个数值的中位数作为主元(key),以此为依据来划分数据。此为三取样优化法。
void QuickSort(int a[] ,int low,int high) //三取样快速排序
{
if(low>=high)
{
return;
}
int mid=(low+high)/2;
if(a[mid]>a[high]) swap(a[mid],a[high]); /*将最大值
if(a[low]>a[high]) swap(a[low],a[high]); 放在high位置 * /
if(a[mid]>a[low]) swap(a[low],a[mid]); //将中值放在 low位置
int index=partition(a,low,high);
QuickSort(a,low,index-1);
QuickSort(a,index+1,high);
}
C代码(优化二): 采取随机数作为主元,即从数组中随机选取一个元素作为排序的主元。
void QuickSort(int a[] ,int low,int high)
{
if(low>=high)
{
return;
}
int rand= low + (int) rand()%(high -low+1 )
swap(a[low],a[rand]);
int index=partition(a,low,high);
QuickSort(a,low,index-1);
QuickSort(a,index+1,high);
}
快排应用:寻找第K小元素:
int SelectKMin(int *p,int left,int right,int k)
{
if(left == right && k == 1)
{
return p[left];
}
int index = partition(p,left,right);
int pos = index - left + 1;
if(k <= pos)
{
return SelectKMin(p,left,index,k);
}
else
{
return SelectKMin(p,index+1,right,k - pos);
}
}