1.將乙個問題劃分為同一型別的若干子問題,子問題最好規模相同
2.對子問題求解(一般使用遞迴方法)
3.有必要的話,合併子問題的解,得到原始問題的答案
下圖描述的是將乙個問題劃分為兩個較小子問題的例子,也是最常見的情況:
1.主要思想
對於乙個需要排序的陣列a[0…n-1],將其一分為二:a[0…n/2-1]和a[n/2…n-1] (n/2向下取整),對每個子陣列遞迴排序,然後把這兩個排好序的子陣列合併為乙個有序陣列
mergesort(a[0...n-1])
//遞迴呼叫mergesort對陣列a[0...n-1]進行排序
//輸入:乙個可排序陣列a[0...n-1]
//輸出:非降序排列陣列a[0...n-1]
if n>1
copy a[0....n/2-1] to b[0....n/2-1]
copy a[n/2....n-1] to c[0....n/2-1]
mergesort(b[0....n/2-1])
mergesort(c[0....n/2-1])
merge(b,c,a) //合併
merge(b[0....p-1],c[0....q-1],a[0....p+q-1])
//將兩個有序陣列合併為乙個有序陣列
//輸入:兩個有序陣列b[0....p-1]和c[0....q-1]
//輸出:有序陣列a[0....p+q-1]
i=0;j=0;k=0
while i可參考:合併(歸併)排序原理及**實現(c/c++)
2.分析
演算法是否原地排序
是否穩定
最好、最壞、平均時間複雜度
空間複雜度
是否基於比較
歸併排序否是
o(nlogn)、o(nlogn)、o(nlogn)
o(n)
是優點:穩定
缺點:需要線性的額外空間
3.兩類主要變化形式
1.演算法自底向上合併陣列的乙個個元素對,然後再合併這些有序對,以此類推:分治法-合併排序
2.把陣列劃分為待排序的多個部分,再對他們遞迴排序,最後將其合併在一起:如上所述。
1.主要思想
快速排序就是給基準找正確索引位置的過程.
如下圖所示,假設最開始的基準資料為陣列第乙個元素23,則首先用乙個臨時變數去儲存基準資料,即tmp=23;然後分別從陣列的兩端掃瞄陣列,設兩個指示標誌:low指向起始位置,high指向末尾.
首先從後半部分開始,如果掃瞄到的值大於基準資料就讓high減1,如果發現有元素比該基準資料的值小或等於基準資料(如上圖中18<=tmp),就將high位置的值賦值給low位置 ,結果如下:
然後開始從前往後掃瞄,如果掃瞄到的值小於基準資料就讓low加1,如果發現有元素大於基準資料的值或者等於基準資料(如上圖46=>tmp),就再將low位置的值賦值給high位置的值,指標移動並且資料交換後的結果如下:
然後再開始從後向前掃瞄,原理同上,發現上圖11<=tmp,則將high位置的值賦值給low位置的值,結果如下:
然後再開始從前往後遍歷,直到low=high結束迴圈,此時low或high的下標就是基準資料23在該陣列中的正確索引位置.如下圖所示.
此時基準已經位於它在有序陣列中的最終位置,比基準數大的都放在基準數的右邊,比基準數小的放在基準數的左邊
接下來採用遞迴的方式分別對基準數前半部分和後半部分用同樣的方法排序,當前半部分和後半部分均有序時該陣列就自然有序了。
參考:快速排序—(面試碰到過好幾次)
quicksort(a[a...b])
//用quicksort對子陣列排序
//輸入:陣列a[0...n-1]的子陣列a[a...b]
//輸出:非降序排列的子陣列a[a...b]
if a=p
repeat j-- until a[j]<=p
swap(a[i],a[j])
until i>=j
swap(a[i],a[j]) //撤銷最後一次交換
swap(p,a[j]) //交換基準和a[j]
return j
2.為什麼當遇到與基準元素相等的元素時值得停止掃瞄?
因為當遇到有很多相同元素的陣列時,這個方法可以將陣列分的更加平均(左右),從而使演算法執行得更快。如果我們遇到相同元素時繼續掃瞄,對於乙個具有n個相同元素的陣列來說,最後得到的兩個子陣列的長度可能分別是n-1和0,在掃瞄了整個陣列後只將問題的規模減1。
3.分析
演算法是否原地排序
是否穩定
最好、最壞、平均時間複雜度
空間複雜度
是否基於比較
快速排序是否
o(nlogn)、o(n^2)、o(nlogn)
o(logn)~o(n)
是4.優化
1.更好的基準選擇方法:例如隨機快速排序,它使用隨機元素作為基準;三平均劃分法以陣列最左邊、最右邊和最中間的元素的中位數作為基準。
2.當子陣列足夠小時(5~15個),改用插入排序方法,或者不再對小陣列進行排序,而是在快速排序快結束後再使用插入排序的方法對整個近似有序的陣列進行排序。
3.一些劃分方法的改進。例如三路劃分,將陣列分成三段,每段的元素分別小於、等於、大於基準元素。
1.主要思想
設有序陣列a[low…high]是當前的查詢區間,首先確定該區間的中點位置mid=(low+ high)/2 , 然後將待查的值與a[mid].key比較:
(1)若k= =a[mid],則查詢成功並返回該元素的下標;
(2)若k< a[mid],新的查詢區間是左子表a[low…mid-1];
(3)若k> a[mid],新的查詢區間是右子表a[mid+ 1…high]
1.主要思想
計算兩個n位整數a和b的積,其中n是乙個正的偶數。
把a的前半部分記為a1,a的後半部分記為a2;對於b,分別記為b1和b2。
c2=前半部分之積
c1=(a1+a2)*(b1+b2)-(c2+c0) 兩部分和的積減去c2和c0
c0=後半部分之積
如果n/2也是偶數,我們可以用相同的方法來計算c2,c1和c0。當n=1時,遞迴就停止了。或者當我們認為n已經足夠小了,小到可以直接對這樣大小的數相乘時,遞迴也可以停止了。
演算法設計與分析複習 分治法演算法描述
分治 劃分 解子問題 組合 每個遞迴演算法均可以轉換為迭代演算法 include include 尋找最大最小元素,最大比較次數 3 n 2 2 minmax low,high if high low 1 if arr low arr high return arr low arr high els...
演算法設計與分析 分治法(js實現)
特徵能否利用分治法完全取決於問題是否具有這條特徵,如果具備了前兩條特徵,而不具備第三條特徵,則可以考慮貪心演算法或動態規劃。偽 divide and conquer p if p n0 adhoc p 解決小規模的問題 divide p into smaller subinstances pl,p....
演算法設計與分析之分治法 棋盤覆蓋
棋盤覆蓋問題要求在2 k 2 k 個方格組成的棋盤中,你給定任意乙個特殊點,用一種方案實現對除該特殊點的棋盤實現全覆蓋。建立模型如圖 解決方案就是利用分治法,將方形棋盤分成4部分,如果該特殊點在某一部分,我們就去遞迴他,如果不在某一部分,我們假設乙個點為特殊點,同樣遞迴下去,知道全覆蓋。左上角的子棋...