一.算法介绍
快速排序(Quicksort 有时称为partition-exchange排序)是一种有效的排序算法,作为系统的方法将一个数组的元素。当实现,它可以两到三倍的速度比其主要竞争对手,归并排序和堆排序。快速排序是一种比较,这意味着它可以排序项“小于”关系的任何类型的定义(在形式上,全序)。在高效的实现,它不是一种稳定的,这意味着平等的相对顺序排序项不保存。快速排序数组可以就地操作,需要少量额外的内存来执行排序。https://en.wikipedia.org/wiki/Quicksort#Analysis_of_randomized_quicksort
二.复杂度分析
平均而言,该算法需要O(n log n)比较n项进行排序。在最坏的情况下,它使O(n2)比较,尽管这种行为是罕见的。
三.算法思想及步骤
1) 分解(Divide): 数组A[p..r]被划分成为两个(可能为空)子数组A[p..q-1]和A[q+1..r],使得A[p..q-1]中的每个元素都小于等于 A(q),而且小于等 于A[q+1..r]中的元素,下标q也在划分的过程中进行计算.
2) 解决(Conquer):通过递归调用快速排序,对子数组A[p..q-1],A[q+1..r]排序.
3) 合并(Conbine):因为两个子数组是就地排序的,将他们的合并不需要操作:整个数组A[p..r]已排序.
伪码如下:
//QUICKSORT(A,p,r)
if p < r
then q <-- PARTITION(A,p,r)
QUICKSORT(A,p,q-1)
QUICKSORT(A,q+1,r)
QUICKSORT函数中三个参数的意义: A待排序数组 p 排序开始标志位 r 待排序数组A的长度.
如果想要给一个完整的数组A排序,那么就需要执行QUICKSORT(A,1,length[A]).
从上面的排序过程可以看出3,4都是递归调用解决子问题,而就地排序的过程在PARTITION中进行。所以重点理解PARTITION。
//PARTITION(A,p,r)
x <-- A[r]
i <-- p-1
for j <-- p to r-1
<span style="white-space:pre"> </span>if A[j] <= x
<span style="white-space:pre"> </span>then i <-- i+1
<span style="white-space:pre"> </span>exchange A[i] <--> A[j]
exchange A[i+1] <--> A[r]
return i+1
示例模拟
不怎么好用的在线演示请点击这里Quick-Sort
Wiki图库给出如下模拟
四.C代码
#include<stdio.h>
void quicksort(int a[],int l,int r)
{
if(l<r)
{
int i,j,t;
i=l,j=r,t=a[l];
while(i<j)
{
while(i<j&&a[j]>=t) // 从右向左找第一个小于t的数
j--;
if(i<j)
a[i++]=a[j];
while(i<j&&a[i]<t) // 从左向右找第一个大于t的数
i++;
if(i<j)
a[j--]=a[i];
}
a[i]=t;
quicksort(a,l,i-1);
quicksort(a,i+1,r);
}
}
int main()
{
int a[20],n;
while(scanf("%d",&n)!=EOF&&n)
{
for(i=0;i<n;i++)
scanf("%d",&a[i]);
quicksort(a,0,n-1);
for(i=0;i<n;i++)
printf("%d ",a[i]);
puts("");
}
return 0;
}