排序算法的研究在历史上一直没有停止过,最初的简单排序如:选择排序,冒泡排序,插入排序。平均算法复杂都为O(n^2),这以后很多年都没有大的进步。直到希尔排序的出现才打破O(n^2)的限制达到O(n^3/2);最后又出现堆排序,归并,快速排序等性能更好的排序算法复杂度达到nlogn;行了不多废话了。
快速排序的基本原理:选择一个初始值,然后左右搜索,将比这个值大的往右移小的向左移。如此递归最后完成排序。具体的解释随便找一本数据结构看看吧。当然对于那些极端情况及改进方式在此不再多提。快速排序算法写法较多在此我仅展示自认为书写较简洁的。
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
//划分
int partion(int a[],int l, int h)
{
int i = l;
int j = h;
int temp = a[l];
while(i < j)
{
while(i<j && temp <a[j])
j--;
if(i<j)
{
swap(&a[i],&a[j]);
i++;
}
while(i<j && temp >a[i])
i++;
if(i<j)
{
swap(&a[i],&a[j]);
j--;
}
}
return i;
}
void QuickSort(int a[], int l, int h)
{
if(l >=h) return;
int i=partion( a, l , h);
QuickSort(a,l,i-1);
QuickSort(a,i+1,h);
}
快速排序主要运用分治的思想及将一个大问题划分为几个相同的小的问题进行解答。下面我们来提出一个问题。
假如我们需要找出一个数组或者文件中的最大或者最小的K个值,怎么办呢?
1,首先我们可以将其先排序再取前K或后K就可以解决。最快nlogn + K;
2,采用堆排序的思想,构造一个K的堆,首先将前K个数入堆,再将剩下的每个和对顶比较,在调整。具体维持小堆还是大堆,根据具体情况自己判断。如果找最大维持一个小堆,找最小维持一个大堆。
3,采用快速排序的思想,稍作修改就O了。
在此我只给出快速排序的递归和分递归程序。
//递归版本
int quickselect1(int a[], int l, int h,int k)
{
if(l>=h) return 0;
int i = partion(a,l,h);
if(i==k)
return i;
if(i < k)
quickselect1(a,i+1,h,k);
if(i>k)
quickselect1(a,l,i-1,k);
}
递归算法虽然简单,但是由于每次都要递归调用,函数出栈入栈开销较大所以个人比较偏好非递归。所有的递归一半都可以转化为堆栈来处理,实现起来比较复杂但是本例并不是很复杂。
//非递归版本
int quickselect2(int a[], int l, int h,int k)
{
int i;
while(l<h)
{
i = partion(a,l,h);
if(i==k)return i;
if(i < k) l = i+1;
if(i>k) h = i-1;
}
}
欢迎拍砖