快速排序是一种排序算法,最坏情况运行时间为θ(n2),但其最佳期望运行时间为θ(nlgn),并且θ(nlgn)记号中隐含的常数因子很小,快排是在就地排序的一种排序算法。快排是基于分治思想的,与归并排序一样。快速排序是一种不稳定的排序算法,因为算法实现过程中涉及到元素交换。
思路:
(1)分解:数组A[n]被划分两个字数组A[0..q-1]和A[q+1..n],使得对于数组A[0..q-1]中的元素都小于A[q], A[q+1..n]中的元素都大于等于A[q]。此时A[q]就得排好序。
(2)解决:通过递归调用快速排序,对字数组A[0..q-1]和A[q+1..n]进行排序
(3)合并:因为两个字数组已经是就地排好序的了,整个数组已经排好序了。
void quicksort(int A[],int p,int r)
{
int q;
if(p<r)
{
q=partition(A,p,r);
quicksort(A,p,q-1);
quicksort(A,q+1,r);
}
}
int partition(int A[],int p,int r)
{
int x,i,j,middle;
x = A[r];
i = p-1;
for(j=p;j<=r-1;j++)
{
if(A[j]<=x)
{
i++;
middle=A[i];
A[i]=A[j];
A[j]=middle;
}
}
middle=A[r];
A[r]=A[i+1];
A[i+1]=middle;
return (i+1);
}
假设输入的数组为A[8]={2,8,7,1,3,5,6,4};下面来实现输入过程,length=8;main函数调用quicksort(A,0,length-1)即quicksort(A,0,7)。
此处举例一次快排的执行过程:
基准选择数组的最后一个元素A[r].
1.步骤7中for循环执行过程见下图:j<=r-1;即j<=6;x=4
(1)j从0到6进行循环:i=-1;j=0
判断if(A[j]<=x):A[j]=A[0]=2<4,执行
i++;
middle=A[i];
A[i]=A[j];
A[j]=middle;
即i=0;A[i]与A[j]交换;
(2)j从1到6进行循环:i=0;j=1
判断if(A[j]<=x):A[j]=A[1]=8>4;不满足。执行下一次for循环
(3)j从2到6进行循环:i=0;j=2
判断if(A[j]<=x):A[j]=A[2]=7>4;不满足。执行下一次for循环
(4)j从3到6进行循环:i=0;j=3
判断if(A[j]<=x):A[j]=A[3]=1<4;满足,执行i++;A[i]与A[j]交换;
i++;
middle=A[i];
A[i]=A[j];
A[j]=middle;
i=1;A[i]=A[1]=8;A[j]=A[3]=1;如下图
(5)j从4到6进行循环:i=1;j=4
判断if(A[j]<=x):A[j]=A[4]=3<4;满足,执行i++;A[i]与A[j]交换;
i=2;A[i]=A[2]=7;A[j]=A[4]=3;如下图:
(6)j从5到6进行循环:i=2;j=5
判断if(A[j]<=x):A[j]=A[5]=5>4;不满足。执行下一次for循环
(7))j从6到6进行循环:i=2;j=6
判断if(A[j]<=x):A[j]=A[6]=6>4;不满足。执行下一次for循环
(8)j++;j=7,跳出for循环。此时数组如下图:图a
2.接下来执行步骤8,执行完后如图b
返回i+1=3,即主元素的下标。
最后第一次递归执行的结果图如下:
下次递归,主元素不再进行排序,分别对其左边和右半边的数组进行排序。即2、1、3和7、5、6、8分别递归。此处不再一一举例。
最后给出程序运行的结果:
源代码下载地址源代码