用单向扫描法实现快速排序
快速排序的核心就是对数组的划分:如何划分才能让数组的左边都小于某个值,右边都大于某个值?
对数组的划分方法有:单向扫描法,双向扫描法,三分法。
这里介绍单向扫描法。
快排思想
无论是哪种方法,快排的整体框架都可以用这样的伪代码描述
/* 伪代码:
* QuickSort(A,start,end)
* if(start<end)
* int p=partition(A,start,end)//找到划分点
* QuickSort(A,start,p-1)//划分点左侧进行快排
* QuickSort(A,p+1,end)//划分点右侧进行快排
* /
单向扫描法
1)定义主元,扫描指针(初始化指向主元之后的元素),bigger指针(初始化指向数组尾)
2)扫描数组,小于等于主元的放在左边,扫描指针右移
大于主元的,交换bigger和扫描指针指向的元素,bigger左移
3)扫描完毕后将主元和bigger指向的元素进行交换
主元的位置为什么在bigger处?
假设现在sp指针移动到了bigger处,首先比较bigger指向的元素和主元的大小
情况一:小于等于主元,则sp右移,循环结束
情况二:大于主元,则交换,bigger左移,循环结束
得出无论在哪种情况,bigger指向的都是最后一个小于等于主元的元素
sp指向的都是第一个大于主元的元素
前面说过,划分的标准就是主元左边都小于主元,右边都大于主元
那么主元就应该放在第一个大于主元的元素之前,也就是bigger所指处
最终代码
import java.util.Arrays;
public class QuickSortSingleDirection {
public static void main(String[] args) {
int n[]= {9,8,7,6,5,4,3,2,1};
QuickSort(n,0,n.length-1);
System.out.println(Arrays.toString(n));
}
private static void QuickSort(int[] n, int i, int j) {
if(i<j)
{
int p=partition(n,i,j);//找到划分点
QuickSort(n,i,p-1);//对划分点左侧进行快排
QuickSort(n,p+1,j);//对划分点右侧进行快排
}
}
private static int partition(int[] n, int i, int j) {
int pivot=n[i],sp=i+1,bigger=j;//定义主元,扫描指针,bigger指针
while(sp<=bigger)
{
if(n[sp]<=pivot)//小于等于主元的都放在左边,sp右移
sp++;
else//大于的都放在右边,交换sp和bigger指向的元素
{
int temp=n[bigger];
n[bigger]=n[sp];
n[sp]=temp;
bigger--;//bigger左移
}
}
//交换主元和bigger指向的元素
int temp=n[bigger];
n[bigger]=n[i];
n[i]=temp;
return bigger;
}
}