快速排序利用了分治策略。分治策略可以分為3個步驟:
對乙個典型的子陣列a[p..r]進行快速排序的分治過程如下:
快速排序的偽**如下:
,為了排序陣列a的全部元素,初始呼叫quicksort(a, 1, a.length)。
其中最關鍵的部分就是陣列的劃分partition,它實現了對子陣列a[p..r]的原址重排。偽**如下:
這裡的partition程式選擇x=a[r]作為主元,並圍繞著它來劃分陣列。
隨著程式的增加,陣列被劃分成4個區域,如下圖所示:
其中:指標 i 一直指向小值陣列的最後乙個元素,j指向大值陣列末尾的下乙個元素。
partition的一次迭代過程中會出現兩種情況:
(a)如果a[j]>x,需要做的只是將j值加1:
(b)a[j]<=x,則將i值加1,並交換a[i]和a[j],在將j值加1,使迴圈不變數保持不變。
在partition的最後,將主元與最左的大於x的元素進行交換,就可以將主元移動到它在陣列中的正確位置,並返回主元的新下標。
快速排序的執行時間依賴於劃分是否平衡,而平衡與否又依賴於用於劃分的元素。
3.1 最壞情況劃分
當劃分產生的兩個子問題分別包含了n-1個元素和0個元素,這是極不平衡的劃分。假設演算法的每一次遞迴都出現了這種不平衡的劃分,演算法執行時間的遞迴式可以表示為:
可以解得:
所以,如果在演算法的每一層遞迴上,劃分都是最大程度不平衡的,那麼演算法的時間複雜度為:
3.2 平均情況
在最平衡的劃分中,partition得到的兩個子問題的規模都不大於n/2。演算法執行時間的遞迴式為:
可以解得:
另外,只要是劃分是常數比例的,甚至好的和差(極不平衡)的劃分交替出現時,快速排序演算法和全是好的劃分時一樣,仍然是
在演算法中引入隨機性,使得演算法對所有的輸入都能獲得較好的期望效能。
從a[p..r]中隨機選擇乙個元素作為主元。為了達到這一目的,首先將a[r]與從a[p..r]隨機選擇的元素交換。通過對序列p..r隨機抽樣保證主元素
x=a[r]是等概率從r-p+1個元素中選取的。
下面是randomized-partition和randomized-quicksort的偽**:
在使用randomized-partition,輸入元素互異的情況下,快速排序演算法的期望執行時間為
randomized-partition:
int partition(int data, int length, int start, int end)
2:
7:int index = randominrange(start, end);
8: swap(&data[index], &data[end]);
9:
10:int small = start - 1;
11:for (index = start; index < end;++index)
12:
20: }
21: }
22: ++small;
23: swap(&data[small], &data[end]);
24:
25:return small;
26: }quicksort:
void quicksort(int data, int length, int start, int end)
2:
7:int index = partition(data, length, start, end);
8:if (index >start)
9:
12:if (index13:
16: }
快速排序學習
下面是我寫的 public function quicksortme a array,left int,right int void 一般來說,插入排序都採用in place在陣列上實現。具體演算法描述如下 1.從第乙個元素開始,該元素可以認為已經被排序 2.取出下乙個元素,在已經排序的元素序列中從...
快速排序學習
簡單原理 快速排序是對氣泡排序的改進,用分而治之的思想,先找到乙個基準數,利用基準數進行一輪排序,將所有比它小的數都放在左邊,再將所有比它大的數都放在它右邊,然後返回基準數的位置,進行下一輪排序,下一輪將分別對基準數左右兩邊進行排序,依次迴圈,直到最後排序完成。實現 import org.codew...
C 快速排序 隨機快速排序 學習記錄
都是網上的資源,侵刪。快速排序演算法以及其他演算法的時間以及空間複雜度 我認為比較好理解的思路 1 先從數列中取出乙個數作為基準數。2 分割槽過程,將比這個數大的數全放到它的右邊,小於或等於它的數全放到它的左邊。3 再對左右區間重複第二步,直到各區間只有乙個數。坑填數1 i l j r 將基準數挖出...