分治演算法 簡單了解

2021-06-28 03:03:45 字數 2592 閱讀 8052

部分內容來自:  感謝原作者!

這種將整個問題分解為若干個小問題來處理的方法稱為分治法。被分解出來的小問題與原問題有相同的解法,這樣便於演算法的計算(往往採用遞迴)。

分治法的控制流程:

a 判斷是否滿足最小處理條件,或者說滿足了最小規模函式,然後進行處理,或者返回。【有的可能沒有】

b 如果沒有滿足最小規模,那麼就開始對資料進行分塊處理。

c 遞迴呼叫a過程

d 結合一下分治後的結果。

1、  折半搜尋

乙個已經排好序的陣列中尋找某乙個指定元素。那麼便可以折半查詢,即一直比較陣列中間的元素和指定元素的大小關係,然後決定了下一輪查詢的範圍(縮小到了一半)。此處採用的是乙個迴圈,記錄住left和right,並不斷的調整lefe和right下標位置。

2、  遞迴求最大最小值

通過分治的思想,不斷的求出一半中的最大值和最小值,然後再比較左邊和右邊的最小值以及左邊和右邊的最大值。在此處獲得的想法就是看遞迴函式的引數如何設定,比如要算出最大值和最小值,那麼便可以設定兩個引數,這個引數如果是引用,那麼數值在每一層遞迴中都可以使用到。

3、  歸併排序

先提到了插入排序:思路就是從第二個位置開始掃瞄陣列,然後把剛遇到的元素插入到前面元素中去,使得前面的元素保持一定的順序。

歸併排序就是通過分治的思想把分開後有序的串拼接到一起。分為兩部分,乙個是mergesort函式,主要用於分治,然後通過merge函式把結果合併到一起。注意的是merge函式的引數是開始,中間位置和結束位置,是普世的位置,不是從0開始的。歸併排序之所以快是因為當把一些有序的陣列再合併到一起的時候更加的快捷高效。

歸併排序中需要留意的地方:縮小到什麼規模的時候可以結束;另外在用陣列的時候涉及到頻繁的移位。提出了使用鏈結的歸併排序演算法。即通過之前提到的鏈結圖來做,而不再是陣列。

4、快速排序

快速排序的思想是通過分治的方式,使得某元素左邊的元素總是小於分割點處的元素,而分割點處元素的右面元素都大於該元素。演算法也是分為兩部分,quicksort,主控制函式以及partition函式(使用者對指定範圍內的函式進行操作,即某元素左邊小於某個值;某元素右面的元素大於某個值。)

排序演算法   最壞複雜度   平均複雜度

氣泡排序    o(n2)          o(n2)

插入排序    o(n2)          o(n2)

選擇排序    o(n2)          o(n2)

快速排序    o(n2)          nlog(n)

歸併排序    nlog(n)         nlog(n)

5、選擇問題:在乙個陣列中選出第k小的元素

最容易想到的辦法就是先排序,然後選出第k小的元素;或者採用分治的思想,採用快速排序中partition的思想,找到小於某元素的所有元素和大於該元素的所有元素。這樣在再找第k個的話便更加的方便和快捷。最壞情況下的複雜度為on2,平均複雜度為on.因為知道了左邊小於某元素的大概多少個,大於某元素的多少個。先籠統的劃分了乙個範圍。需要注意的就是在partselect中要不斷的調整範圍。

上述的方法在最差的情況下時間複雜度為o(n2),怎麼進一步優化呢。在呼叫partition函式的時候就是為了找出分界點在哪,那麼怎麼能快速精確的定位分界點資料呢。可以先把整個資料進行分段,然後把每一段的中間元素放到該端的最前端,這樣陣列的最前面就是記錄每一段的中間資料了。然後再從前段這些資料中找到中間元素。以此元素作為分界值。一面發生最壞的情況。

6、矩陣的乘法

兩個n*n矩陣的相乘時間複雜度為on3,相加的時間複雜度為on2,這個可以通過想象**的實現過程就可以。

於是有人想到了採用分治的思想,就是把矩陣分成一塊一塊的,然後再進行分塊計算。雖然思想不錯,但是複雜度沒有變化,還是on3。此處可以學學如何推到的時間複雜度。規模降低之後的表示方式,t(n)、t(n/2)表示,以及多出來的操作時什麼,複雜度如何表示等。

分治之後的複雜度仍然是on3,於是有人想著如何降低乘法的次數,這樣便可以降低複雜度,於是有人最終通過數學推倒,發現可以把原來分治之後的八次乘法降低為七次懲罰操作和18次加減法計算。目前矩陣最好的時間複雜度是on2.36。

7、直線上的最接近點對問題

首先想到的方法就是把這些點先排序,然後便可以通過一遍掃瞄知道最接近點對。通過分治的思想解決方式如下:按照中位數分為左右兩部分,然後在左右兩邊都找最接近點對,然後再判斷兩邊最接近點之間的距離。從而可以找出最接近點對。

8、平面上最接近點對問題

同樣可以通過x座標來把所有的點分成一塊一塊的,然後求出每一塊的最近點對。不同塊之間的最近點對計算的時候就要有篩選了,不是計算所有的,而是在限定好的區域內進行選取。時間複雜度為nlogn

簡單了解遞迴演算法

從前有座山,山里有座廟,廟裡有個老和尚,正在給小和尚講故事呢!故事是什麼呢?從前有座山,山里有座廟,廟裡有個老和尚,正在給小和尚講故事呢!故事是什麼呢?從前有座山,山里有座廟,廟裡有個老和尚,正在給小和尚講故事呢!故事是什麼呢?函式內部是可以呼叫其他函式的,這種呼叫就是函式的巢狀呼叫。遞迴就是 函式...

分治演算法的簡單應用

1.要求2n個數的中位數,採用分治策略。每次劃分後,都會去掉一半的數,只剩原來一半的數。遞推關係式為 t n t n 2 o 1 由master定理,可得時間複雜度為o logn include include define n 1000000 using namespace std int a n...

分治演算法 入門簡單例項

求最大值和最小值,相信再簡單不過了,只要乙個迴圈遍歷,然後每次比較最大的和最小的值,然後遍歷完後就得到了最大值和最小值了。就是先排序,然後最大值和最小值就是頭尾了。這裡用分治法來求最大值和最小值了。如下 include stdio.h int aa void get max min int s,in...