package com.joker.counts;
public class FastSort {
/**
* 快速排序
* 原理,总体思路为 分而治之(递归)
* 具体操作:选中一个元素为基数,以这个基数为参照,和每个元素相比较,通过交换位置,将比该基数大的元素放在数组尾部,比该基数小的元素放在数组头部。当已这个基数重新排序出来之后,
* 数组分为三个部分,[小于基数数组][基数][大于基数数据]。这时,分而治之,小于基数数组,大于基数数组分别再递归调用,即可完成排序。
* @param counts
* @param start
* @param end
*/
public static void sort(int[] counts,int start,int end){
int left = start;
int right = end;
//选取基数
int base = counts[start];
//当left==right时,说明遍历完了,也就是完成[小于基数数组][基数][大于基数数据]。这是第一次遍历
//重点:交换位置:
//不管是从前往后查找还是从后往前查找,需要交换位置的元素为本次查找到的数据和上一次查找到的数据,如果没有上一次(第一次循环,则上一次为选取的基数位置。)
while(right>left){
//此处为什么是选取了数组第一个元素为基数,要从数组最后一个元素往前开始遍历?
//这和算法无关,只是为了编程方便,因为找到的元素和基数元素交换位置,
//如果选取了第一个元素为基数,而从第一个开始遍历,即需要比较left和left++之后的left的值,无法编写。而从数组尾部开始遍历,则比较方便。
//同理如果选取数组尾部的元素为基数,则从第一个元素开始遍历方便很多。
while(right>left&&counts[right]>=base)
right--;
//找到了目标元素
if(counts[right]<base){
int temp = counts[right];
counts[right] = counts[left];
counts[left] = temp;
}
//找到了目标元素
while(right>left&&counts[left]<=base)
left++;
if(counts[left]>base){
int temp = counts[right];
counts[right] = counts[left];
counts[left] = temp;
}
}
//left>start 说明从前往后看,基数位置发生了变化,[小于基数数组]那么以基数为分割点,从新递归排序。
if(left>start) sort(counts,0,left-1);
//end>right 说明从后往前看,基数位置发生了变化,[大于基数数组]那么以基数为分割点,从新递归排序。
if(end>right) sort(counts,right+1,end);
}
public static void main(String[] args) {
int[] counts = new int[] { 3, 2, 5, 6, 2, 1, 7, 3 };
sort(counts, 0, counts.length-1);
for (int i = 0; i < counts.length; i++) {
System.out.println(counts[i]);
}
}
}