快速排序-----三指针分区法
1、算法的思想
根据快速排序的算法思想,再加一条:我们在进行第一次排序完之后,只需要再进行大于主元,和小于主元那部分区域的排序即可,并不需要再进行等于主元这部分的比较
例子:
还未排序的:5, 10, 5, 2, 8, 5, 5, 5, 1, 9
第一次排序得到的结果:2, 1, 5, 5, 5, 5, 5, 8, 10, 9
之后,进行下一轮排序时,我们只需要排序[2,1]和[8,10,9]这部分
2、如何分区
首先:对于普通的快速排序算法,我们还需要多一个指针,用于指定等于主元的起始位置
头指针的查询逻辑变为
1、头指针指向的元素小于主元,头指针位置的元素和equals位置的元素进行交换,并且头指针++ equals++
2、头指针等于主元,头指针++
3、大于主元 就需要和尾指针进行交换
尾指针查询逻辑依旧为普通的快速排序的逻辑
1、找到一个小于主元的元素,就需要和首指针进行交换
3、注意点
直到头指针超过尾指针,equals所处最终的位置是小于或者等于主元的,再进行下一轮排序时,需要将(equals-1)位置的元素与主元。
1)如果equals所处位置元素小于主元,那么就可以知道equals也是超过尾指针的,所以也需要进行(equals-1)处理,再进行交换
2)如果equals所处位置元素等于主元,那么equals-1位置的元素肯定小于主元,所以也需要进行(equals-1)处理,再进行交换
4、代码
public void sort_1(Comparable[] comparables,int start,int end){
//如果相等,表示只有一个元素,就需要进行比较,直接返回
if(start>=end){
return;
}
int equals = start+1;
int i = start + 1;
int j = end;
Comparable temp = comparables[start];
for(; i<=j ;) {
//找到一个比主元小【或者等于】的
while(temp.compareTo(comparables[j])<0){
if(i>j){
break;
}
j--;
}
//找到一个大于主元的
while(temp.compareTo(comparables[i])==0 || temp.compareTo(comparables[i])>0){
//如果相等,那么equals位置不变,而比较位置加1
if(temp.compareTo(comparables[i])==0){
i++;
}else if(temp.compareTo(comparables[i])>0){ //如果是小于主元的,那么就需要进行交换【与equals位置的元素进行交换】
change(comparables,equals,i);
equals++;
i++;
}
if(i>j){
break;
}
}
//跳转
if(i>j){
break;
}
//交换
change(comparables,i,j);
}
//交换
change(comparables, start, equals - 1);
//进行下一轮的排序
sort_1(comparables, start, equals - 2);
sort_1(comparables,j+1,end);
}
//进行元素交换的方法
public void change(Comparable[] comparables,int start,int end){
if(start==end){
return;
}
Comparable comparable = comparables[start];
comparables[start] = comparables[end];
comparables[end] = comparable;
}