一、什麼是快速排序?
快速排序是對冒泡排序的改進,本質上都是通過交換兩個元素來消除逆序。
在冒泡排序中,由於掃描過程中只對相鄰的兩個元素進行比較,因此在互換兩個相鄰元素時只能消除一個逆序。
而在快速排序中,能通過兩個不相鄰的元素的交換,消除待排序記錄中的多個逆序,則速度較冒泡排序有極大的提高。
二、快速排序實現算法思路:
(1)、快速排序算法是一個遞歸過程:
一個問題能通過遞歸來解決,則說明其能夠將一個大問題分解爲無數個小問題;而且這些小問題的解決算
法與大問題的解決算法是一毛一樣的,只是問題規模的差別。
所以快速排序可以分解爲無數的小問題,每一個小問題的解決方法都一樣。
(2)、那麼這個解決方法是什麼呢?
首先在待排序記錄中找一個支柱元素結點(一般都是找序列的第一個元素,因爲簡單),使用這個支柱結
點將序列劃分爲兩個子序列。
怎麼劃分呢? 將大於等於支柱結點值的元素放到支柱結點的右邊(子序列1);將小於支柱結點值得元
素放到支柱結點的左邊(子序列2);然後理所應當這個支柱結點就在兩個子序列的交接點上。在此時,我們
如果把整個序列看成三個元素:子序列2 < 支柱結點 < 子序列1,是不是有序的呢?
(3)、理解了這一點,就好辦了!
我們把一個最開始的大序列通過支柱結點劃分爲兩個子序列,再將每個子序列劃分爲兩個子子序列。。。
當所有的子序列的長度爲0 或 1 時,而且經過(2)步驟的元素交換後。那麼當前整個序列就已經是一個有序
序列了。
下圖爲一次劃分實例:
<1>. 將序列的第一個元素用變量x保存(則下標爲0的元素位置空下來了),用low 和 high兩個下標變量來存
儲序列兩端的下標。其中low是序列左端下標(下標爲 0),high爲序列的右端下標(下標爲序列長度- 1)
, low < high ;
<2>. 因爲low位置是空的,所以可以放一個元素;因爲是左端空了,所以從右端由 high 從右端向左端遞減尋
找比支柱結點 x 值小的元素放入 low 的位置,low下標向後挪一個位置(low++)。然後是 high位置空了。
<3>. 因爲high位置是空的,所以可以放一個元素;因爲是右端空了,所以從左端由 low 從左端向右端遞增尋
找比支柱結點 x 值大的元素放入 high的位置,high下標向前挪一個位置 (high--)。然後又是 low 位置空
了。 由此轉去循環執行<2>、<3>過程。直到 low < high 條件不在被滿足,退出循環。
<4>. 將支柱結點的值保存在low = high 的下標位置。
<5>. 一趟排序完成。
源代碼:
#include <stdio.h>
/*
**功能: 進行一趟快速排序
**參數說明:
**@record : 子序列數組; @low : 序列左端下標; @high : 序列右端下標
**返回值 : 支柱結點下標
*/
int QKPass(int record[], int low, int high)
{
int x = record[low]; //保存支柱結點值
while (low < high)
{
/*
* 因爲low位置是空的,所以可以放一個元素;因爲是左端空了,所以從右端由
* high 從右端向左端遞減尋找比支柱結點 x 值小的元素放入 low 的位置,low下
* 標向後挪一個位置(low++)
*/
while (low < high && record[high] >= x)
{
high--;
}
if (low < high)
{
record[low] = record[high];
low++;
}
/*
* 經過上面操作後,high位置是空的,所以可以放一個元素;因爲是右端空了,
* 所以從左端由low 從左端向右端遞增尋找比支柱結點 x 值大的元素放入 high的
* 位置,high下標向前挪一個位置 (high--)。
*/
while (low < high && record[low] < x)
{
low++;
}
if (low < high)
{
record[high] = record[low];
high--;
}
}
record[low] = x; //將支柱結點的值保存在low = high的位置
}
/*
**功能: 快速排序入口點
**參數說明:
**@record : 記錄序列數組; @low : 序列左端下標; @high : 序列右端下標
**返回值 : 無
*/
void QKSort(int record[], int low, int high)
{
if (low < high)
{
int position; //保存支柱結點下標
position = QKPass(record, low, high); //進行一趟快速排序,找到支柱結點的下標
QKSort(record, low, position - 1); //對序列2進行快速排序
QKSort(record, position + 1, high); //對序列1進行快速排序
}
}
int main(void)
{
int record[] = { 48,62,35,77,55,14,35,98 };
int len = sizeof(record) / sizeof(record[0]);
int i = 0;
printf("排序前: \n");
for (i = 0;i < len;i++)
{
printf("%d ", record[i]);
}
puts("");
QKSort(record, 0, len - 1);
printf("排序後: \n");
for (i = 0;i < len;i++)
{
printf("%d ", record[i]);
}
puts("");
return 0;
}
運行截圖: