一、什麼是快速排序
引用百度百科的解釋:快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然後再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。
二、快速排序實現過程
1、分析過程
首先,在這一串數字中挑一個基準數,作爲排序的參考,將大於該基準數的數字放在後面,小於基準數的數字放在前面。
然後,這樣一來,一串數字分成了兩部分,左部分都比基準數小,右部分都比基準數大。接着,同樣的方法,再分別從左右部分都挑出一個基準數,同樣作爲排序的參考,同樣將大於該基準數的數字放在後面,小於基準數的數字放在前面。
以此類推,直至大小排序完成爲止。
2、具體數字模擬過程
- 假設有如下一串數字:“22,1,43,23,6,34,2,7,22,88,32,54”
- 爲了方便,我們將第一個數字22作爲基準數。
- 假設一“探針”從右往前遍歷找到一個比22小的數,然後另一“探針”從左往右遍歷找到一個比22大的數,交換它們位置。直到兩“探針”相遇,此時左邊的都比22小,右邊的都比22大。
- 然後將分割好數字串的按以上方法排序
a:右探針從右往左勘測,找到比22小的數,那麼探針停在7位置上;
b:左探針從左往右勘測,找到比22大的數,那麼探針停在43位置上;
c:交換7和43;
如下圖:
繼續a步驟:右探針找到比22小的數,探針停在了2位置上;
繼續b步驟:左探針找到比22大的數,探針停在了23位置上;
繼續c步驟:交換2和23
如下圖:
繼續a步驟:右探針找到比22小的數,探針停在了6位置上;
繼續b步驟:左探針右移與右探針重合,發現6比22小,那麼交換6和22
如下圖:
最終,整串數字被22分割成兩部分,左邊全部比22小,右邊全部比22大。
然後,以此類推,按照上述方法,將左右部分分別排序,如下左半部分排序:
同理,可得出右半部分排序。
三、快速排序代碼實現和效率
1、代碼
public static void main(String[] args) {
int[] array = {22,1,43,23,6,34,2,7,22,88,32,54};
int start = 0;
int end = array.length - 1;
quickSort(array, start, end);
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
public static void quickSort(int[] a, int left, int right) {
int start = left;
int end = right;
int key = a[left];
while (end > start) {
// 從後往前比較,如果沒有比關鍵值小的,比較下一個,直到有比關鍵值小的交換位置
while (end > start && a[end] >= key)
end--;
if (a[end] <= key) {
// 如果比基準數小交換位置
int temp = a[end];
a[end] = a[start];
a[start] = temp;
}
// 從前往後比較,如果沒有比關鍵值大的,比較下一個,直到有比關鍵值大的交換位置
while (end > start && a[start] <= key)
start++;
if (a[start] >= key) {
// 如果比基準數大交換位置
int temp = a[start];
a[start] = a[end];
a[end] = temp;
}
// 左右探針重合後,以基準值分爲左右兩部分,左邊都比基準值小,右邊都比基準值大
}
// 然後遞歸,直到排完所有數字
if (start > left) quickSort(a, left, start - 1);
if (end < right) quickSort(a, end + 1, right);
}
2、效率
快速排序(Quicksort)是對冒泡排序的一種改進。
那麼以下是十萬個隨機數通過兩種排序方式用時的對比:
(1)代碼
public static void main(String[] args) {
int a[] = new int[100000];
// 生成10萬個隨機數
for (int i = 0; i < 100000; i++) {
int num = (int) (Math.random() * 100000);
a[i] = num;
}
int b[] = a;
long l = System.currentTimeMillis();
int start = 0;
int end = a.length - 1;
quickSort(a, start, end);
System.out.println("100000個隨機數快速排序用時 = " + (System.currentTimeMillis() - l));
long s = System.currentTimeMillis();
// 冒泡排序
bubooSort(b);
System.out.println("100000個隨機數冒泡排序用時 = " + (System.currentTimeMillis() - s));
}
public static void quickSort(int[] a, int left, int right) {
int start = left;
int end = right;
int key = a[left];
while (end > start) {
// 從後往前比較,如果沒有比關鍵值小的,比較下一個,直到有比關鍵值小的交換位置
while (end > start && a[end] >= key)
end--;
if (a[end] <= key) {
// 如果比基準數小交換位置
int temp = a[end];
a[end] = a[start];
a[start] = temp;
}
// 從前往後比較,如果沒有比關鍵值大的,比較下一個,直到有比關鍵值大的交換位置
while (end > start && a[start] <= key)
start++;
if (a[start] >= key) {
// 如果比基準數大交換位置
int temp = a[start];
a[start] = a[end];
a[end] = temp;
}
// 左右探針重合後,以基準值分爲左右兩部分,左邊都比基準值小,右邊都比基準值大
}
// 然後遞歸,直到排完所有數字
if (start > left) quickSort(a, left, start - 1);
if (end < right) quickSort(a, end + 1, right);
}
private static void bubooSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
(2)輸出結果
100000個隨機數快速排序用時 = 58
100000個隨機數冒泡排序用時 = 2884
在10萬條數據時,所用時間長短顯而易見,那麼在大數據情況下,這種對比將更加明顯。所以可以得出:快速排序是對冒泡排序的優化和改進。