演算法分析——分治思想之快速排序
優化一個演算法的最根本的原理就是減少演算法的基本操作。
分治法的設計思想是,將一個難以直接解決的大問題,分割成一些規模較小的相同問題,以便各個擊破,分而治之。
於是,在快速排序中,我們通過分割陣列的思路來將大問題分割成小規模的問題,與二分搜尋法類似的是,在二分法
中,我們需要進行的操作是搜尋,是在已經排好序的基礎上通過一分為二來減少搜尋範圍,降低時間複雜度,二分搜
索中通過尋找中位數,將陣列分為左右兩邊,通過與中位數的比較確定待查詢數所在的範圍,即,我們在判斷是否中
位數與待查詢數的大小的同時,還利用判斷的結果,將搜尋的範圍縮小,這就與最基本的遍歷法中僅僅比較是否相等
有了很大的差距,換句話講,就是在二分搜尋中,我們通過一次比較進行了兩種操作,而在傳統的遍歷中,我們通過
一次比較僅僅只進行一種操作。於是,在排序中,我們是否也可以考慮這種思路。傳統的氣泡排序中,我們僅僅在一
個數與其他數的比較時確定了一個數的位置(這裡寫的有點難理解的感覺),我們在進行比較的同時是否能仿照二分
搜尋法一般,比較的同時縮小排序的範圍,即我們通過選取一個基準元素將帶排序陣列劃分為兩個陣列,在基準元素
與陣列元素進行比較的同時,將大於基準元素的數放到陣列的右側,小於基準的數放到陣列左側,在通過同樣的思路
對被劃分而成兩個個子問題進行相同的操作,直到最終子問題的大小等於3。
下面就是相關的實現步驟:
1.分解:以a[p]為基準元素將a[p:r]劃分為三段a[p:q-1],a[q+1:r]使得a[p:q-1]中任何元素小於等於a[q],a[q+1]中任何元素
大於等於a[q]下標q在劃分過程中確定
2.遞迴求解:通過遞迴呼叫快速排序演算法,分別對a[p:q-1]和a[q+1]進行排序
3:合併:由於對a[p:q-1]和a[q+1:r]的排序是就地進行的所以a[p:q-1]和a[q+1:r]都已排好的序後不需要執行任何計算,
就已排好序.
void Algorithm::qSort(int a[],int left,int right) { if(left<right) { int middle=partition(a,left,right); qSort(a,left,middle-1); qSort(a,middle+1,right); } } int Algorithm::partition(int a[],int left,int right) { int first=left+1; int last=right; int number=a[left]; int i=0; while(true) { while(a[first]<number&&first<=right) { first++; } while(a[last]>number) { last--; } if(first>=last) { break; } else { int temp=0; temp=a[last]; a[last]=a[first]; a[first]=temp; } } a[left]=a[last]; a[last]=number; return last; }