數據結構基礎(4) --快速排序
來源:程序員人生 發布時間:2015-01-07 08:58:38 閱讀次數:2586次
快速排序是最流行的,也是速度最快的排序算法(C++ STL 的sort函數就是實現的快速排序); 快速排序(Quicksort)是對冒泡排序的1種改進。由C. A. R. Hoare在1962年提出。它的基本思想是:通過1趟排序將要排序的數據分割成獨立的兩部份,其中1部份的所有數據都比另外1部份的所有數據都要小,然后再按此方法對這兩部份數據分別進行快速排序,全部排序進程可以遞歸進行,以此到達全部數據序列變成有序序列。其算法的特點就是有1個樞軸(pivot), 樞軸左側的元素都小于/等于樞軸所指向的元素, 樞軸右側的元素都大于樞軸指向的元素;
快速排序算法思想:
設要排序的數組是A[0], ..., A[N⑴],首先任意選取1個數據作為standard(通常選用數組的最后1個數)作為關鍵數據,然后將所有比它小的數都放到它前面,所有比它大的數都放到它后面(其實只要保證所有比他小的元素都在其前面,則后1條件則自動滿足了),這個進程稱為1趟快速排序。值得注意的是,快速排序不是1種穩定的排序算法,也就是說,多個相同的值的相對位置或許會在算法結束時產生變動。(信息來源:百度百科)
1次劃分
目標:
找1個記錄,以它的關鍵字/下標作為”樞軸/pivot”,凡是值小于樞軸的元素均移動至該樞軸所指向的記錄之前,凡關鍵字大于樞軸的記錄均移動至該記錄以后。
導致1趟排序以后,記錄的無序序列R[s..t]將分割成兩部份:R[s..i⑴]和R[i+1..t],且
R[j].value ≤ R[i].value ≤ R[j].value
//實現
template <typename Type>
int partitionBy3Loop(Type *array, int p, int r)
{
int i = p;
int j = r+1; //j:超越末尾元素額下1位置
Type x = array[p]; //將最左側的元素作為樞軸元素
//將<x的元素交換到左側區域
//將>x的元素交換到右側區域
while (true)
{
//找到1個比x大(>=x)的元素
while (i < r && array[++i] < x);
//找到1個比x小(<=x)的元素
while (array[--j] > x);
if (i >= j)
break;
//交換
std::swap(array[i], array[j]);
}
//將樞軸元素與array[p]進行交換
std::swap(array[p], array[j]);
//返回樞軸
return j;
}
/**說明:
幾近國內所有的數據結構與算法的教材中的Partition實現都
類似于上面的那1種, 雖然易于理解,但實現過于復雜;
<算法導論>中給出了另外一種實現方式,
該方式雖然不容易于理解(其實明白其原理以后你就會愛上她),但是比較容易實現!
*/
template <typename Type>
int partitionBy1Loop(Type *array, int p, int r)
{
Type x = array[r]; //x作為終究樞軸所指向的元素
//i指向的是樞軸左側的最后1個元素
//也就是與x左鄰元素的下標
int i = p - 1;
//j則不斷的尋覓下1個<=x的元素
for (int j = p; j < r; ++j)
{
if (array[j] <= x)
{
++ i;
std::swap(array[i], array[j]);
}
}
std::swap(array[i+1], array[r]);
//終究使得所有(i+1)左側的元素都<=array[i+1],
//因此, 所有array[i+2:r]的元素都是大于array[i+1]的
return i+1;
}
快速排序
首先對無序的記錄序列進行“1次劃分”,以后分別對分割所得兩個子序列“遞歸”進行快速排序。
//實現
template <typename Type>
void quickSort(Type *array, int p, int r)
{
if (p < r)
{
int pivot = partitionBy1Loop(array, p, r);
quickSort(array, p, pivot⑴);
quickSort(array, pivot+1, r);
}
}
快速排序的時間復雜性
假定1次劃分所得樞軸位置 i = k,則對 n 個記錄進行快排所需時間:
T(n) = {Tpass(n) + T(k⑴) + T(n-k) |Tpass(n)為對 n 個記錄進行1次劃分所需時間}
若待排序列中記錄的關鍵字是隨機散布的,則 k 取 1 至 n 中任意1值的可能性相同。
由此可得快速排序所需時間的平均值為:
設 Tavg(1)≤b,則可得結果:

因此:快速排序的時間復雜度為O(nlogn)
若待排記錄的初始狀態為按關鍵字有序時,快速排序將墮落為起泡排序,其時間復雜度為O(n^2)。
為避免出現這類情況,需在進行1次劃分之前,進行“預處理”,即:先對 R(s).key, R(t).key 和 R[?(s+t)/2?].key,進行相互比較,然后取關鍵字為3個元素中居中間的那個元素作為樞軸記錄。
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈