快速排序算法——java

  思想:快速排序算法利用分治思想,通過一個基準元素將待排數組分成左右兩部分,左邊部分均比基準元素小,右邊部分均比基準元素大,然後對左右兩部分分別遞歸調用快速排序算法,最終實現排序的目的。

  面試中較爲常見的算法之一就是快速排序,快速排序在實際排序應用中也是最好的選擇,因爲它的平均性能非常好,它的期望複雜度爲nlgn,另外,它還是一種穩定的排序方法。快速排序利用分治思想,將待排序數組分成左右兩個部分,然後對其分別遞歸調用快速排序算法。

  下面通過一個例子介紹快速排序算法的思想,假設要對數組a[10]={6,1,2,7,9,3,4,5,10,8}進行排序,首先要在數組中選擇一個數作爲基準值,這個數可以隨意選擇,在這裏,我們選擇數組的第一個元素a[0]=6作爲基準值,接下來,我們需要把數組中小於6的數放在左邊,大於6的數放在右邊,怎麼實現呢?

  我們設置兩個「哨兵」,記爲「哨兵i」和「哨兵j」,他們分別指向數組的第一個元素和最後一個元素,即i=0,j=9。首先哨兵j開始出動,哨兵j一步一步地向左挪動(即j–),直到找到一個小於6的數停下來。接下來哨兵i再一步一步向右挪動(即i++),直到找到一個數大於6的數停下來。

 

  最後哨兵j停在了數字5面前,哨兵i停在了數字7面前。此時就需要交換i和j指向的元素的值。

 

  交換之後的數組變爲a[10]={6,1,2,5,9,3,4,7,10,8}:

 

  第一次交換至此結束。接下來,由於哨兵i和哨兵j還沒有相遇,於是哨兵j繼續向前,發現比6小的4之後停下;哨兵i繼續向前,發現比6大的9之後停下,兩者再進行交換。交換之後的數組變爲a[10]={6,1,2,5,4,3,9,7,10,8}。

 

  第二次交換至此結束。接下來,哨兵j繼續向前,發小比6小的3停下來;哨兵i繼續向前,發現i==j了!!!於是,這一輪的探測就要結束了,此時交換a[i]與基準的值,數組a就以6爲分界線,分成了小於6和大於6的左右兩部分:a[10]={3,1,2,5,4,6,9,7,10,8}。

 

  至此,第一輪快速排序完全結束,接下來,對於6左邊的半部分3,1,2,5,4,執行以上過程;對於6右邊的半部分9,7,10,8,執行以上過程,直到不可拆分出新的子序列爲止。最終將會得到這樣的序列:1 2 3 4 5 6 7 8 9 10,到此,排序完全結束。

代碼如下:

package 快速排序;

 

import java.util.Arrays;

 

/**

 * 快速排序

 * 思路:快速排序算法利用分治思想,通過一個基準元素將待排數組分成左右兩部分,左邊部分均比基準元素小,右邊部分均比基準元素大,然後對左右兩部分分別遞歸調用快速排序算法,最終實現排序的目的。

 */

public class quickSort2 {

public static void main(String[] args) {

//定義一個數組

int[] arr = {3,4,6,5,3,1,7,2,8,9};

 

//調用方法,快速排序

quickSort(arr);

 

//打印數組

System.out.println(Arrays.toString(arr));

}

 

//快速排序對外提供的訪問接口

public static void quickSort(int[] arr) {

quickSort(arr,0,arr.length-1);

}

 

private static void quickSort(int[] arr, int low, int high) {

if(low >= high){

return;

}

//進行一次排序,並返回排序後基準元素所在的下標

int pivotIndex = partition(arr,low,high);

//遞歸調用快速排序算法

quickSort(arr, low, pivotIndex-1);

quickSort(arr, pivotIndex+1,high);

}

 

//分治思想分割數組

private static int partition(int[] arr, int low, int high) {

 int i = low;//讓a[i]作爲基準元素

         while(low<high){

          //從右至左遍歷出比基準元素小的值(等於的情況要麼給右邊,要麼給左邊)

             while(low<high&&arr[high]>=arr[i]){

                     high--;

             }

             //從左至右遍歷出比基準元素大的值

             while(low<high&&arr[low]<arr[i]){

                     low++;

             }

             //將右邊找到的比基準元素大的值與左邊找到的比基準元素小的值交換位置

             int p = arr[low];

             arr[low] = arr[high];

             arr[high] = p;

         }

         //最終的結果low與high重合,且這個值一定小於等於基準元素

         //(因爲先從右到左找大值,再從左到右找小值,所以這裏是arr[low];

         //如果反過來,這裏就是arr[low-1])

         int p = arr[low];

         arr[low] = arr[i];

         arr[i] = p;

         

         return low;

}

}