交換排序共包含兩種算法,冒泡排序和快速排序
一、冒泡排序
(Bubble Sort)是一種最簡單的排序算法,將第一個記錄和第二個記錄的關鍵字進行比較,若爲逆序,則進行交換,然後繼續向後移動進行比較,以此類推,直至第n-1個記錄和第n個記錄的關鍵字進行過比較爲止,這個過程稱爲第一趟冒泡排序。第二趟排序對前n-1個記錄進行同樣操作。
值得注意的是,冒泡排序的結束條件是“在一趟排序過程中沒有進行過交換的操作”。
容易看出,若初始序列爲“正序”,則只需要進行一趟排序,反之“逆序”的情況下,需要進行n-1趟排序,所以總的時間複雜度爲O(n^2)
二、快速排序
(Quick Sort)是對冒泡排序的一種改進,基本思想是通過一趟排序將待排記錄分割成獨立的兩部分,其中一部分記錄的關鍵字均比另一部分記錄的關鍵字小,分別排序。
選取一個樞紐pivotkey,通常選擇第一個關鍵字,選擇兩個指針low和high,他們的初值分別爲low和hign,則首先從high所指位置向前搜索找到第一個關鍵字小於pivotkey的記錄和樞紐記錄互相交換,然後從low所指位置起向後搜索,找到第一個關鍵字大於pivotkey的記錄和樞紐記錄互相交換,重複直到low=high爲止。
Partition將序列一分爲二,左面都比pivotkey小,右面都比pivotkey大,返回樞紐的位置。對兩邊分別進行快排,即Partition。
時間複雜度分析:平均時間爲T(n)=k*n*ln^n,k爲某個常數,在所有同數量級的現金排序方法中,快排的常熟因子k最小,因此就平均時間而言,快排是目前被認爲是最好的一種內部排序方法。
平均時間複雜度O(n*logn)
當基本有序的時候,是冒泡排序,時間複雜度爲O(n^2),所以爲了改進他,通常在L[low],L[hign],L[(low+high)/2]三個數之間選擇一箇中間的數作爲樞紐。
同冒泡排序,如果一個子序列沒有進行交換,就沒有必要對這個子序列進行排序了。
空間複雜度:快速排序需要一個棧空間來實現遞歸,如果每次都是均勻分割兩個子序列,則棧的最大深度爲(以2爲底n的對數)+1,最壞情況下,棧的最大深度爲n,如果每次都能先對長度短的子序列進行快速排序,棧的最大深度可以降低爲O(logn)
測試:
int Partition(int L[], int low, int high)
{
L[0] = L[low];
int pivotkey = L[low];
while (low < high)
{
while (low < high && L[high] >= pivotkey)
--high;
L[low] = L[high];//此時high位置的數據比pivotkey的小,所以要放到low的位置
while (low < high && L[low] <= pivotkey)
++low;
L[high] = L[low];
}
L[low] = L[0];
return low;//樞紐位置
}
//主函數調用QSort(L, 1, L.length)
void QSort(int L[], int low, int high)
{
if (low < high)
{
int pivotlocation = Partition(L, low, high);
QSort(L, low, pivotlocation - 1);
QSort(L, pivotlocation + 1, high);
}
}
int main()
{
int L[] = {0, 49, 38, 65, 97, 76, 13, 27, 49};
QSort(L, 1, 8);
for (int i = 1; i <= 8; i++)
cout << L[i] << endl;
}