原文鏈接:http://www.orlion.ga/201/
一、划分算法
1、划分
划分是快速排序的根本機制。划分數據就是把數據分成兩組,所有大於特定值的數據在一組,所有小於特定值的在一組。比如將{3,1,9,0,4,7,2,6,5,8}以特定值為5划分為{3,1,0,4,5}和{9,0,7,6,8}
2、划分算法
划分算法由兩個指針來完成,這兩個指針分別指向數組的兩頭,左指針leftPtr向右移動而右指針rightPtr向左移動,實際上leftPtr和rightPtr初始化時是在左右邊的各減一位的位置,這是因為它開始算法前它們都要分別的加一和減一。
當leftPtr遇到比特定值小的值時它繼續右移,因為這個數據項的位置已經在數組的小於特定值得一邊了。當遇到比特定值大的數時,它就停下來。類似的,當rightPtr遇到比特定值大的數時就繼續左移,當遇到比特定值小的數時就停下來。當都停下來的時候leftPtr和rightPtr都指向了在數組錯誤一方位置上的數據項,所以交換這兩個數據項。交換之后,繼續移動兩個指針,當指向的數據項在數組的錯誤的一方時,再次停止然后交換數據。
3、划分算法的java描述
// 划分算法
public static void divide(long[] arr , int eleNum){
int leftPtr = 0 , rightPtr = eleNum-1;
int middle = 5;
while (true) {
while (leftPtr < eleNum && arr[leftPtr] < middle) {leftPtr++;}
while (rightPtr > -1 && arr[rightPtr] > middle){rightPtr--;}
if (leftPtr >= rightPtr){
// 已經划分完畢
break;
} else {
// 交換
arr[leftPtr] = arr[leftPtr] ^ arr[rightPtr];
arr[rightPtr] = arr[rightPtr] ^ arr[leftPtr];
arr[leftPtr] = arr[leftPtr] ^ arr[rightPtr];
}
}
System.out.println(Arrays.toString(arr));
}
二、快速排序
1、快速排序算法
在大多數情況下,快速排序都是最快的排序算法,時間復雜度為O(N*logN)(這只是對內部排序或者說是隨機存儲器內的排序而言,對在磁盤文件中的數據進行排序,其他的排序算法可能會更好)。
快速排序算法本質上通過將一個數組通過划分算法划分為兩個子數組,然后遞歸的調用自身為每一個子數組進行快速排序來實現。對這個基本的設計進行一些加工就是快速排序算法了。
快速排序中對划分算法中中間值(即一中描述的特定值)的指定的方法有很多種,其中對算法效率比較好的就是"三數據項取中值"方法,具體就是取數組最左邊值和最右邊值以及數組中間位置值這三個數據項中的中間值。(在下面的代碼中用方法medianOf3()進行了描述,該方法也做了一個操作就是對這三個數據項進行了排序。
2、快速排序代碼
封裝到一個QuickSort類中:
package ml.orlion.sort;
import java.util.Arrays;
public class QuickSort {
private long[] arr;
public QuickSort(long[] arr){
this.arr = arr;
}
// 快速排序算法
public void doQuickSort(int left , int right){
int center = medianOf3(left , right);
if (0 < center && center < right - 1) {
int middle = divide(left , right , arr[center]);
// 遞歸對左邊的子數組進行排序
doQuickSort(0 , middle);
// 遞歸對右邊的字數組進行排序
doQuickSort(middle , right);
}
}
// 划分算法
public int divide(int left , int right , long middle){
int size = right - left + 1;
while(true){
while(left < size - 1 && arr[left] < middle){
left++;
}
while(right > -1 && arr[right] >= middle){
right--;
}
if (left > right) {
break;
} else {
swap(left , right);
}
}
return right+1;
}
// 三數據項取中值
private int medianOf3(int left , int right){
int center = (right+left)/2;
if (arr[left] > arr[center])
swap(left , center);
if (arr[left] > arr[right])
swap(left , right);
if (arr[center] > arr[right])
swap(center , right);
return center;
}
// 交換兩個數
private void swap(int left , int right){
arr[left] = arr[left] ^ arr[right];
arr[right] = arr[right] ^ arr[left];
arr[left] = arr[left] ^ arr[right];
}
public void display(){
System.out.println(Arrays.toString(arr));
}
}
然后調用測試:
long[] arr = {7,1,2,4,5,3,0,6,8,9};
QuickSort qs = new QuickSort(arr);
qs.doQuickSort(0, 9);
qs.display();
