快速排序就這麼簡單
從前面已經講解了氣泡排序、選擇排序、插入排序了,本章主要講解的是快速排序,希望大家看完能夠理解並手寫出快速排序的程式碼,然後就通過面試了!如果我寫得有錯誤的地方也請大家在評論下指出。
快速排序的介紹
來源百度百科:
快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通過一趟排序將要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料都要小,然後再按此方法對這兩部分資料分別進行快速排序,整個排序過程可以遞迴進行,以此達到整個資料變成有序序列。
快速排序是面試出現的可能性比較高的,也是經常會用到的一種排序,應該重點掌握。
前面一個章節已經講了遞迴了,那麼現在來看快速排序就非常簡單了。
一、第一趟快速排序
通過一趟排序將要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料都要小
百度百科的話並沒有說到重點,更簡單的理解是這樣的:在陣列中找一個支點(任意),經過一趟排序後,支點左邊的數都要比支點小,支點右邊的數都要比支點大!
現在我們有一個陣列:int arr[]={1,4,5,67,2,7,8,6,9,44};
經過一趟排序之後,如果我選擇陣列中間的數作為支點:7(任意的),那麼第一趟排序後的結果是這樣的:{1,4,5,6,2,7,8,67,9,44}
那麼就實現了支點左邊的數比支點小,支點右邊的數比支點大
二、遞迴分析與程式碼實現
現在我們的陣列是這樣的:{1,4,5,6,2,7,8,67,9,44}
,既然我們比7小的在左邊,比7大的在右邊,那麼我們只要將”左邊“的排好順序,又將”右邊“的排好序,那整個陣列是不是就有序了?想一想,是不是?
又回顧一下遞迴:”左邊“的排好順序,”右邊“的排好序,跟我們第一趟排序的做法是不是一致的?
只不過是引數不一樣:第一趟排序是任選了一個支點,比支點小的在左邊,比支點大的在右邊。那麼,我們想要”左邊“的排好順序,只要在”左邊“部分找一個支點,比支點小的在左邊,比支點大的在右邊。
..............
在陣列中使用遞迴依照我的慣性,往往定義兩個變數:L
和R
,L
指向第一個陣列元素,R
指向在最後一個陣列元素
遞迴出口也很容易找到:如果陣列只有一個元素時,那麼就不用排序了
所以,我們可以寫出這樣的程式碼:
public static void main(String[] args) {
int[] arr = {1, 4, 5, 67, 2, 7, 8, 6, 9, 44};
quickSort(arr, 0, 9);
System.out.println("Java3y " + arr);
}
/**
* 快速排序
*
* @param arr
* @param L 指向陣列第一個元素
* @param R 指向陣列最後一個元素
*/
public static void quickSort(int[] arr, int L, int R) {
int i = L;
int j = R;
//支點
int pivot = arr[(L + R) / 2];
//左右兩端進行掃描,只要兩端還沒有交替,就一直掃描
while (i <= j) {
//尋找直到比支點大的數
while (pivot > arr[i])
i++;
//尋找直到比支點小的數
while (pivot < arr[j])
j--;
//此時已經分別找到了比支點小的數(右邊)、比支點大的數(左邊),它們進行交換
if (i <= j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
//上面一個while保證了第一趟排序支點的左邊比支點小,支點的右邊比支點大了。
//“左邊”再做排序,直到左邊剩下一個數(遞迴出口)
if (L < j)
quickSort(arr, L, j);
//“右邊”再做排序,直到右邊剩下一個數(遞迴出口)
if (i < R)
quickSort(arr, i, R);
}
複製程式碼
三、快速排序優化
來源:www.cnblogs.com/noKing/arch…
我這裡簡單概括一下思路,有興趣的同學可到上面的連結上閱讀:
- 隨機選取基準值base(支點隨機選取)
- 配合著使用插入排序(當問題規模較小時,近乎有序時,插入排序表現的很好)
- 當大量資料,且重複數多時,用三路快排
四、擴充套件閱讀
原理都是一樣的,在細節上有些變化而已
- 它是交換完畢後記錄支點的角標,然後再劈開兩半進行遞迴呼叫
C語言程式碼實現:
void QuickSort ( int*arr,int low, int high);
int FindPos ( int*arr,int low, int high);
int FindPos ( int*arr,int low, int high)
{
int val = arr[low];
while (low < high) {
while (low < high && arr[high] >= val)
--high;
arr[low] = arr[high];
while (low < high && arr[low] <= val)
++low;
arr[high] = arr[low];
}
arr[low] = val;
return low;
}
void QuickSort ( int arr[], int low, int high)
{
int pos;
if (low < high) {
pos = FindPos(arr, low, high);
QuickSort(arr, low, pos - 1);//劈兩半,左邊
QuickSort(arr, pos + 1, high); //右邊
}
return;
}
int main ()
{
int arr[ 6]={ 5, 3, -88, 77, 44, -1 } ;
int i;
QuickSort(arr, 0, 5);
for (i = 0; i < 6; i++)
printf("%d ", arr[i]);
printf("\n");
return 0;
}
複製程式碼
如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y