天天看點

快排 java_快速排序 java實作 (原理-優化) 三路快排

一、基本的快速排序

在數組中選取一個元素為基點,然後想辦法把這個基點元素移動到它在排好序後的最終位置,使得新數組中在這個基點之前的元素都小于這個基點,而之後的元素都大于這個基點,然後再對前後兩部分數組快速排序,直到數組排序完成。

快排 java_快速排序 java實作 (原理-優化) 三路快排

代碼實作:

public void quickSorted ( intarr[] ) {int n = arr.length - 1; //閉區間 [0...n]

__quickSorted (arr, 0, n);

}private __quickSorted( int arr[], int L, intR) {if ( (L >=R) {return;

}//将基點移動到最終位置的方法

int p =__partioner(arr, L, R);//遞歸拆分數組

__quickSorted(arr, L, p - 1);

__quickSorted(arr, p+ 1, R);

}

那麼最大的問題就是怎麼把這個基點移動到它最終應該所在的位置。

快排 java_快速排序 java實作 (原理-優化) 三路快排

代碼實作:

private int __partioner ( int arr[], int L, intR ) {int v =arr[L];//[L + 1, j] < v ; [j + 1, i) > v;

int j =L;for ( int i = L + 1; i <= R; i++) {if ( arr[i]

int tmp = arr[j + 1];

arr[j+ 1] =arr[i];

arr[i]=tmp;

j++;

}

}//交換 arr[j] 和arr[L]

int tmp =arr[j];

arr[j]=arr[L];

arr[L]=tmp;returnj;

}

最終實作:

快排 java_快速排序 java實作 (原理-優化) 三路快排
快排 java_快速排序 java實作 (原理-優化) 三路快排

public void quickSorted ( intarr[] ) {int n = arr.length - 1; //閉區間 [0...n]

__quickSorted (arr, 0, n);

}private __quickSorted( int arr[], int L, intR) {if ( (L >=R) {return;

}//将基點移動到最終位置的方法

int p =__partioner(arr, L, R);//遞歸拆分數組

__quickSorted(arr, L, p - 1);

__quickSorted(arr, p+ 1, R);

}private int __partioner ( int arr[], int L, intR ) {int v =arr[L];//[L + 1, j] < v ; [j + 1, i) > v;

int j =L;for ( int i = L + 1; i <= R; i++) {if ( arr[i]

int tmp = arr[j + 1];

arr[j+ 1] =arr[i];

arr[i]=tmp;

j++;

}

}//交換 arr[j] 和arr[L]

int tmp =arr[j];

arr[j]=arr[L];

arr[L]=tmp;returnj;

}

View Code 快速排序完整代碼

二、快速排序的優化

1.  快速排序的第一次優化,減小遞歸的深度,轉而使用 選擇排序

private __quickSorted( int arr[], int L, intR) {//if ( (L >= R) {//return;//}//快速排序的第一次優化,減小遞歸的深度,轉而使用 選擇排序

if ( R - L <= 15) {

insertSorted(arr, L, R);return;

}

//将基點移動到最終位置的方法

int p =__partioner(arr, L, R);//遞歸拆分數組

__quickSorted(arr, L, p - 1);

__quickSorted(arr, p+ 1, R);

}//減小遞歸的深度轉而使用選擇排序

private void insertSorted(int arr[], int L, intR) {for (int i = L + 1; i <= R; i++) {int i =arr[i];intj;for (j = i; j > L && arr[j - 1] > e; j--) {

arr[j]= arr[j - 1];

}

}return;

}

2. 優化二,基點的選擇随機化

private int __partioner ( int arr[], int L, intR ) {//第二次優化,将基點的選擇随機化

int rand = (new Random().nextInt(R + 1)) +L;//交換最左側和随機點的元素

int tmp =arr[rand];

arr[rand]=arr[L];

arr[L]=tmp;

int v =arr[L];//[L + 1, j] < v ; [j + 1, i) > v;

int j =L;for ( int i = L + 1; i <= R; i++) {if ( arr[i]

int tmp = arr[j + 1];

arr[j+ 1] =arr[i];

arr[i]=tmp;

j++;

}

}//交換 arr[j] 和arr[L]

int tmp =arr[j];

arr[j]=arr[L];

arr[L]=tmp;returnj;

}

三、兩路快排

解決排序的數組中存在多數重複元素的情況

快排 java_快速排序 java實作 (原理-優化) 三路快排

代碼實作

快排 java_快速排序 java實作 (原理-優化) 三路快排
快排 java_快速排序 java實作 (原理-優化) 三路快排

public void quickSorted ( intarr[] ) {int n = arr.length - 1; //閉區間 [0...n]

__quickSorted (arr, 0, n);

}private __quickSorted( int arr[], int L, intR) {//if ( (L >= R) {//return;//}//快速排序的第一次優化,減小遞歸的深度,轉而使用 選擇排序

if ( R - L <= 15) {

insertSorted(arr, L, R);return;

}//将基點移動到最終位置的方法

int p =__partioner(arr, L, R);//遞歸拆分數組

__quickSorted(arr, L, p - 1);

__quickSorted(arr, p+ 1, R);

}private int __partioner ( int arr[], int L, intR ) {//第二次優化,将基點的選擇随機化

int rand = (new Random().nextInt(R + 1)) +L;//交換最左側和随機點的元素

int tmp =arr[rand];

arr[rand]=arr[L];

arr[L]=tmp;int v =arr[L];//兩路快排的實作過程

int i = L + 1;int j =R ;while (true) {while (i <= R && arr[i]

i++;

}while (j >= L + 1 && arr[j] >v) {

j--;

}if (i >j) {break;

}//交換 i 和 j 的位置

inttmp arr[i];

arr[i]=arr[j];

arr[j]=tmp;

}inttmp arr[L];

arr[L]=arr[j];

arr[j]=tmp;returnj;

}//減小遞歸的深度轉而使用選擇排序

private void insertSorted(int arr[], int L, intR) {for (int i = L + 1; i <= R; i++) {int i =arr[i];intj;for (j = i; j > L && arr[j - 1] > e; j--) {

arr[j]= arr[j - 1];

}

}return;

}

View Code 兩路快排代碼實作

四、三路快排

快排 java_快速排序 java實作 (原理-優化) 三路快排

代碼實作:

快排 java_快速排序 java實作 (原理-優化) 三路快排
快排 java_快速排序 java實作 (原理-優化) 三路快排

public static void quickSorted3Ways(intarr[]) {int n = arr.length -1;//arr[0, n] 閉區間

__quickSorted3Ways(arr, 0, n);

}private static void __quickSorted3Ways(int[] arr, int L, intR) {//if (L >= R) {//return;//}//快速排序的第一次優化,減小遞歸的深度,轉而使用 選擇排序

if ( R - L <= 15) {

insertSorted(arr, L, R);return;

}//第二次優化,将基點的選擇随機化

int rand = (new Random().nextInt(R + 1)) +L;//交換最左側和随機點的元素

int tmp =arr[rand];

arr[rand]=arr[L];

arr[L]=tmp;int v =arr[L];//partioner//這三個變量的初始值 , 相當重要

int lt = L; //arr[L + 1, lt] < v

int gt = R + 1; //arr[gt, R] > v

int i =L + 1; //arr[lt + 1, i ) ==v//此處的 i 的比較對象

while (i

SortedHandler.swap(arr, i, lt+ 1);

lt++;

i++;

}else if (arr[i] >v) {

SortedHandler.swap(arr, i, gt- 1);

gt--;

}else{

i++;

}

}

SortedHandler.swap(arr, lt, L);

__quickSorted3Ways(arr, L, lt-1);

__quickSorted3Ways(arr, gt, R);

}

View Code 三路快排

最後附上整篇 關于快速排序從實作到逐漸優化的思路圖 (畫到我懷疑人生了....)

快排 java_快速排序 java實作 (原理-優化) 三路快排