快排的目的其实就是把原序列分成以基准元素为界的两个子序列,左侧子序列小于或等于基准元素,右侧子序列大于基准元素。为了实现这个目的,我们可以从右往左扫描,找小于或者等于基准元素p的数A[j],然后从左向右扫描,找大于基准元素p的数A[i],将A[I[和A[j]交换,一直交替进行,直到i和j相遇为止,这时将基准元素与A[i]交换即可。
以序列(30,24,5,58,18,36,12,42,39)为例:
(1)初始化,i=low,j=high,p=A[low]。
(2)从右往左找,找小于或者等于p的数,找到A[j]=12。
(3)从左往右找,找大于p的数,找到A[I]=58。
A[i]与A[j]交换,i++,j--。
(4)从右往左走,一直找小于或者等于p的数,找到A[j]=18.
(5)从左往右走,一直找大于p的数,这时i=j,停止。
(6)A[I]小于p,A[i]和A[low]交换,返回i的位置,mid=i,第一趟排序结束。
此时,以mid为界,将原数据分成两个子序列,左侧子序列都比p小,右侧子序列都比p大,然后分别对两个子序列(18,24,5,12)、(36,58,42,39)进行快速排序。
以下是具体代码:
#include<bits/stdc++.h>
using namespace std;
int fen(int A[],int low,int high){//划分函数
int i=low,j=high,p=A[low];//定义A[low]为基准元素
while(i<j){
while(i<j&&p<A[j]) j--;//向左扫描
while(i<j&&p>=A[i]) i++;//向右扫描
if(i<j){
swap(A[i++],A[j--]); //A[i]和A[j]交换
}
}
if(A[i]>p){
swap(A[i-1],A[low]);//如果A[i]元素大于基准元素则基准元素和A[i-1]交换
return i-1;//返回基准元素的位置
}
swap(A[i],A[low]);
return i;//返回基准元素的位置
}
void he(int A[],int low,int high){//快速排序
if(low<high){
int mid=fen(A,low,high);//划分
he(A,low,mid-1);//左边快速排序
he(A,mid+1,high);//右边快速排序
}
}
int main(){
int a[1005];
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
he(a,0,n-1);//调用函数
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
}