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]);
}
}
}