快速排序:在每一轮挑选一个基准元素,并让其它比它大的元素移动到一边,小于等于它的元素移动到另一边;
思想:分治法
基准元素选择:随机选择与选择第一个等
元素交换:双边交换与单边交换
一、双边遍历交换实现:
import java.util.Arrays;
/**
* 快速排序
*/
public class FastSortDemo {
/**
* 双边循环递归
*
* @param arr
*/
public static void sort(int arr[], int startIdx, int endIdx) {
if (startIdx >= endIdx) {
return;
}
int baseIdx = getBaseIdxForDoubleLoop(arr, startIdx, endIdx);
sort(arr, startIdx, baseIdx - 1);
sort(arr, baseIdx + 1, endIdx);
}
/**
* 获取下一次到基准下标
* @param arr
* @param startIdx
* @param endIdx
* @return
*/
private static int getBaseIdxForDoubleLoop(int[] arr, int startIdx, int endIdx) {
int base = arr[startIdx];
int leftIdx = startIdx;
int rightIdx = endIdx;
//指针重合停止
while (leftIdx != rightIdx) {
//如果右边指针指向到值大于基准值且下标小于左下标,则往左移
while (arr[rightIdx] > base && rightIdx > leftIdx) {
rightIdx--;
}
//与右指针相反,小于等于基准值则往右移动一次
while (arr[leftIdx] <= base && leftIdx < rightIdx) {
leftIdx++;
}
//交换左右指针指向动值
if (rightIdx > leftIdx) {
int tmp = arr[leftIdx];
arr[leftIdx] = arr[rightIdx];
arr[rightIdx] = tmp;
}
}
//与基准值交换
arr[startIdx] = arr[leftIdx];
arr[leftIdx] = base;
return leftIdx;
}
public static void main(String[] args) {
int[] arr = new int[]{8, 23, 22, 1, 9, 0, 26, 98, 100, 3, 6};
sort(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr));
}
}
结果:
[0, 1, 3, 6, 8, 9, 22, 23, 26, 98, 100]
二、单边循环实现:
首先与双边循环法则一样,选择一个基准值,然后一个指针指向起始位置,接下来从基准元素下一个位置开始遍历;
如果遍历元素小于基准元素,则指针右移一位,指针所在位置元素与最新遍历元素交换位置;
/**
* 单边循环获取基准值
* @param arr
* @param startIdx
* @param endIdx
* @return
*/
public static int getBaseIdxForSingleLoop(int[] arr, int startIdx, int endIdx) {
int base = arr[startIdx];
int mark = startIdx;
for (int i = startIdx + 1; i <= endIdx && mark < endIdx; i++) {
if (arr[i] < base) {
mark++;
int tmp = arr[i];
arr[i] = arr[mark];
arr[mark] = tmp;
}
}
arr[startIdx] = arr[mark];
arr[mark] = base;
return mark;
}
单边与双边循环主要区别在于获取循环获取基准值;
关于源码,已上传到github(https://github.com/DexterMao/DataStructureDemo);