快速排序(Quick Sort)

2022-09-20 06:45:13 字數 3035 閱讀 8648

非穩定排序、原地排序、比較排序

氣泡排序是在相鄰的兩個記錄進行比較和交換,每次交換只能上移或下移乙個位置,導致總的比較與移動次數較多。快速排序是目前應用最廣泛的排序演算法之一。快速排序又稱分割槽交換排序,是對氣泡排序的改進,快速排序採用的思想是分治思想

每次從待排序區間選取乙個元素(一般有多種選取規則,越接近排序後的中位演算法效果越好,因為遞迴樹越平衡)作為基準記錄,所有比基準記錄小的元素都在基準記錄的左邊,而所有比基準記錄大的元素都在基準記錄的右邊。之後分別對基準記錄的左邊和右邊兩個區間進行快速排序,直到將整個線性表排序完成。

快速排序使用分治法來把乙個串(list)分為兩個子串(sub-lists)。具體演算法描述如下:

最好情況:是每趟排序結束後,每次劃分使兩個子檔案的長度大致相等,時間複雜度為$o(nlog n)$。

最壞情況:是待排序記錄已經排好序,第一趟經過$n - 1$次比較後第乙個記錄保持位置不變,並得到乙個$n - 1$個元素的子記錄;第二趟經過$n - 2$次比較,將第二個記錄定位在原來的位置上,並得到乙個包括$n - 2$個記錄的子檔案,依次類推,這樣總的比較次數是:$c_ = \sum_^ (n − i) = n(n − 1) / 2 = o(n^2)%。

可通過隨機選取基準值來盡可能避免最壞情況。

平均情況:$o(nlog n)$

空間複雜度

沒有額外的空間開銷。

左右交替掃瞄、替換。遞迴子串行。

void quick_sort_v1(int *arr, int l, int

r) arr[x] =z;

quick_sort_v1(arr, l, x - 1

); quick_sort_v1(arr, x + 1

, r);

return

;}

減少一邊函式呼叫的代價。

void quick_sort_v2(int *arr, int l, int

r) arr[x] =z;

quick_sort_v2(arr, l, x -1

); l = x + 1

; }

return

;}

與機器學習中通常的無監督概念不同,此處的無監督是指「去監督項」的意思。對於需要頻繁檢查條件的程式來說,減少乙個監督項的檢查,可以顯著提公升效能。

詳細示例見插入排序的無監督優化部分。

void quick_sort_v3(int *arr, int l, int

r) }

while (x <= y);

quick_sort_v3(arr, l, y

); l = x;

} return;}

依據遞迴樹越平衡(矮)效率越高的思路,基準值的選取越靠近實際排序後的中位數快排演算法的效率越好。

所以將基準值的選取方案由最左端改為隨機(資料量越大,隨機的效果越好)。

void quick_sort_v4(int *arr, int l, int

r) }

while (x <= y);

quick_sort_v4(arr, l, y

); l = x;

} return

;}

基準值選取的另一種方案。因為位置處於中間,此時單邊遞迴和無監督優化後的邊界判斷相較於基準值位於最左端來說要簡潔不少,所以該方案更適合優化後的基準值選取。

int median(int *arr, int l, int

r) void quick_sort_v5(int *arr, int l, int

r)

} while (x <=y);

quick_sort_v5(arr, l, y);

l =x;

}return

;}

當子串行較短時用插入排序更合適,子串行較長時快速排序效能更優。

void unguarded_insert_sort(int *arr, int l, int

r)

while (min >l)

for (int i = l + 2; i <= r; i++)

}return;}

void quick_sort_v6(int *arr, int l, int

r) }

while (x<=y);

quick_sort_v5(arr, l ,y);

l =x;

}if (l

return;}

採用快速排序中的partition部分解題。優點是無需完全排序,中間過程即可得解:

//

返回partition完成後基準值的下標

int partition(int *arr, int l, int

r)

arr[l] =z;

returnl;}

//找出中位數

int find_mid(int *arr, int

n)

if (mid

return (n & 0x01) ? arr[mid] : (arr[mid] + arr[mid + 1]) / 2

;}

partition優化(c++):

int partition(int *num, int left, int

right)

return

l;}

思考:為什麼最後返回的一定是left指標指向的位置?】

快速排序 QuickSort

快速排序通常用於排序的最佳的使用選擇,其期望執行時間為 o nlgn 能夠進行就地排序。最壞執行時間為 o n 2 演算法描述 分解 divide 陣列 a beg end 被劃分為兩個子陣列 a beg mid 1 和a mid 1 end 使得a beg mid 1 中的資料都小於 a mid ...

快速排序 quicksort

快速排序 quicksort 是分治法的典型例子,它的主要思想是將乙個待排序的陣列以陣列的某乙個元素x為軸,使這個軸的左側元素都比x大,而右側元素都比x小 從大到小排序 然後以這個x在變換後陣列的位置i分為左右兩個子陣列,再分別進行快速排序,直到子陣列中只有乙個元素為止。快速排序演算法如下 void...

快速排序 QuickSort

1,void quicksort int a,int low,int high 這個函式是排序的遞迴部分,mid就是已經確定的基準元素的位置。2,int partition int a,int low,int high 這個函式幹了兩件事 1 挑出來乙個基準元素 這裡選的是最後乙個作為基準 找它的正...