基本思想
快速排序(Quicksort)是对冒泡排序的一种改进。 快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
例如:
【1,5,4,3,7,10,8,2,9, 6】–(轴6)–>【1,5,4,3,2】【6,8,7,9,10】
–(轴2)–>【1】【2,4,5,3】 --(轴10)–> 【6,8,7,9】【10】
–【1】–(轴3)–>【2,3】【5,4】–(轴9)–>【6,8,7】【9】–【10】
–【1】–【2,3】【4,5】–(轴7)–>【6,7】【8】–【9】–【10】
JAVA代码实现
/**
* 快速排序【单轴】
* 简单思想: 再需要排序的数组中,取一个值作为“轴”,将其他元素与轴的值进行比较,若小于轴,排在左边,若大于轴,排在右边
* 然后将左边排序好的 与 右边排序好的进行同样的操作:即:取一个轴,小于轴的排右边,大于轴的排左边,直到所有的排序完
* 实现一:
* 取数组最右边的值作为“轴”(非强制要求),取最小索引位置为 左索引:left 取最大索引位置减一为 右索引:right
* while循环,left < right 作为循环条件, 然后从左到右 将arr[left] 与“轴”进行比较,若小于等于“轴”,则left++,直到
* 找到第一个大于轴的值;同时从右到左 将arr[right] 与 “轴”进行比较,若大于“轴”,则right++,直到找到第一个小于轴的值;
* 将 left 与 right 交换,再判断 left 是否小于 right
*
* 平均时间复杂度为 O(n*logN) 最差为O(n^2)【此时数组已排好序】
* 空间复杂度 O(log2^N) 递归时,每一次的临时变量占用空间
*/
public class QuickSort extends Sort {
public static void main(String[] args) {
QuickSort qs = new QuickSort();
int[] arr = new int[]{ 7, 3, 2, 6, 8, 1, 9, 5, 4, 6, 10, 6};
qs.print(qs.sortBase(arr, 0,arr.length -1));
DataCheck.checkArithmetic(new QuickSort());
}
@Override
public int[] sort(int[] arr) {
return sortBase(arr, 0, arr.length-1);
}
public int[] sortOne(int[] arr, int leftBound, int rightBound){
if(leftBound >= rightBound){
return arr;
}
int mind = partition(arr, leftBound, rightBound);
sortOne(arr, leftBound, mind - 1);
sortOne(arr, mind + 1, rightBound);
return arr;
}
public int partition(int[] arr, int leftBound, int rightBound){
int povit = arr[rightBound];
int left = leftBound;
int right = rightBound - 1;
while(left <= right){
while(left <= right && arr[left] <= povit){
left++;
}
while(right >= left && arr[right] > povit){
right--;
}
if(left < right){
swap(arr, left, right);
}
}
swap(arr, left, rightBound);
return left;
}
//排序
public int[] sortBase(int[] arr, int leftBound, int rightBound){
if(rightBound-leftBound == 1){
if(arr[leftBound] > arr[rightBound]){
swap(arr, leftBound, rightBound);
}
return arr;
}else if(leftBound >= rightBound){
return arr;
}
int axle = quick(arr, leftBound, rightBound);
sortBase(arr, leftBound, axle-1);
sortBase(arr, axle + 1, rightBound);
return arr;
}
public int quick(int[] arr, int leftBound, int rightBound){
//避免出现已排好序的数组 再排序时 时间复杂度为O(n^2)出现,将随机去轴,并替换掉最后的值
// randowSwap(arr, leftBound, rightBound);
int axle = arr[rightBound];
int left = leftBound;
int right = rightBound - 1;
while(left < right){
//从左到右,找大于轴的第一个
while(left <= right && arr[left] <= axle){
left++;
}
//从右到左,找小于轴的第一个
while(right >= left && arr[right] > axle){
right--;
}
if(left < right){
swap(arr, left, right);
}
}
swap(arr, left, rightBound);
return left;
}
public void randowSwap(int[] arr, int left, int right){
int i = right-left;
if(i > 1){
i = new Random().nextInt(i) + left;
swap(arr, i, right);
}
}
//替换
public void swap(int[] arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//打印int数组
public void print(int[] arr){
for(int i = 0; i < arr.length; i++){
System.out.print(arr[i] + " ");
}
}
}