1. 程式人生 > >幾種演算法思想

幾種演算法思想

1、遞迴法

所謂遞迴,就是指如果需要求解當前狀態就需要求解其依賴的遷移狀態。

一般來說,遞迴需要有邊界條件、遞迴前進段和遞迴返回段。當邊界條件不滿足時,遞迴前進;當邊界條件滿足時,遞迴返回。

採用遞迴描述的演算法通常有這樣的特徵:

1)為求解規模為N的問題,設法將它分解成規模較小的問題;

2)然後從這些小問題的解方便地構造出大問題的解,並且這些規模較小的問題也能採用同樣的分解和綜合方法,分解成規模更小的問題,並從這些更小問題的解構造出規模較大問題的解。

3)這樣的分解方法具有收斂性。即存在一個遞迴返回狀態。

例1.1  求最大公約數--歐幾里德演算法

 

2、窮舉法

所謂窮舉法就是遍歷所有可能的狀態。

例如:密碼的暴力破解法就是採用這種方法。

3、化歸法

所謂化歸法是指,不直接解決原問題,而是把所要解決的問題,經過某種變化,使之歸結為另一個(問題*),再通過(問題*)的求解,把解得結果作用於原有問題,從而使原有問題得解。

化歸的原則是以已知的、簡單的、具體的、特殊的、基本的知識為基礎,將未知的化為已知的,複雜的化為簡單的,抽象的化為具體的,一般的化為特殊的,非基本的化為基本的,從而得出正確的解答.

此在數學上的應用非常常見。同時,一個邏輯問題的解決的一些列子步驟不正是化歸法的體現嗎?

4、迭代法

迭代法也稱輾轉法,是一種不斷用變數的舊值遞推新值的過程。

最常見的迭代法是牛頓法。其他還包括最速下降法共軛迭代法變尺度迭代法最小二乘法線性規劃非線性規劃單純型法懲罰函式法斜率投影法遺傳演算法模擬退火等等。

利用迭代演算法解決問題,需要做好以下三個方面的工作:

1)迭代變數:在可以用迭代演算法解決的問題中,至少存在一個直接或間接地不斷由舊值遞推出新值的變數,這個變數就是迭代變數。

2)迭代關係:指如何從變數的前一個值推出其下一個值的公式(或關係)。迭代關係式的建立是解決迭代問題的關鍵,通常可以使用遞推或倒推的方法來完成。

3)迭代過程:迭代過程的控制通常可分為兩種情況:一種是所需的迭代次數是個確定的值,可以計算出來;另一種是所需的迭代次數無法確定。對於前一種情況,可以構建一個固定次數的迴圈來實現對迭代過程的控制;對於後一種情況,需要進一步分析出用來結束迭代過程的條件。

迭代法都可以轉為遞迴法。迭代法可以理解為具有遞迴性質的非遞迴解法。當然,非遞迴解法還可利用棧的思想。

例4.1 兔子數量問題

描述:一個飼養場引進一隻剛出生的新品種兔子,這種兔子從出生的下一個月開始,每月新生一隻兔子,新生的兔子也如此繁殖。如果所有的兔子都不死去,問到第 12 個月時,該飼養場共有兔子多少隻?

分析: 這是一個典型的遞推問題。我們不妨假設第 1 個月時兔子的只數為 u 1 ,第 2 個月時兔子的只數為 u 2 ,第 3 個月時兔子的只數為 u 3 ,……根據題意,“這種兔子從出生的下一個月開始,每月新生一隻兔子”,則有

  u 1 = 1 , u 2 = u 1 + u 1 × 1 = 2 , u 3 = u 2 + u 2 × 1 = 4 ,……

  根據這個規律,可以歸納出下面的遞推公式:

  u n = u( n - 1 )× 2 (n ≥ 2)

 

5、分治法

所謂分治法,就是分而治之。將一個問題分解為多個規模較小的子問題,這些子問題互相獨立並與原問題解決方法相同。遞迴解這些子問題,然後將這各子問題的解合併得到原問題的解。

適用問題的特徵:

  • 該問題的規模縮小到一定的程度就可以容易地解決
  • 該問題可以分解為若干個規模較小的相同問題,即該問題具有最優子結構性質。所謂最優子結構是指:問題的最優解所包含的子問題的解也是最優的。
  • 該問題所分解出的各個子問題是相互獨立的,即子問題之間不包含公共的子問題

一般實現步驟:分解--->遞迴求解--->合併

例5.1  河內塔問題

例5.2 歸併排序

6、動態規劃

將待求解問題分解成若干個子問題,但是經分解得到的子問題往往不是互相獨立的,如果能夠儲存已解決的子問題的答案,而在需要時再找出已求得的答案,就可以避免大量重複計算。

適合問題的特徵:

  • 在遞迴計算中,許多子問題將被重複計算多次
  • 具有最優子結構性質。所謂最優子結構是指:問題的最優解所包含的子問題的解也是最優的。即滿足最優化原理。

解決步驟:

1)找出最優解性質,劃分子問題

2)遞迴的定義每階段最優值

3)遞迴計算最優值

4)根據計算最優值時得到的資訊,構造最優解

例6.1 求最長公共子串

例6.2 0-1揹包問題

7、貪心演算法

動態規劃是貪心演算法的基礎。貪心演算法是通過做一系列的選擇來給出某一問題的最優解。對演算法中的每一個決策點,做一個當時(看起來是)最佳的選擇。這種啟發式策略並不總是能產生出最優解。

一般步驟:

1)決定問題的最優子結構

2)設計出一個遞迴解

3)證明在遞迴的任一階段,最優選擇之一總是貪心選擇。那麼,做貪心選擇總是安全的。

4)證明通過做貪心選擇,所有子問題(除一個以外)都為空。

5)設計出一個實現貪心策略的遞迴演算法。

6)將遞迴演算法轉換成迭代演算法。

通常直接做出貪心選擇來構造子結構,以產生一個待優化解決的子問題。更一般地,可以根據以下步驟設計貪心演算法:

1)將優化問題轉化成一個這樣的問題,即先做出選擇,再解決剩下的一個子問題。

2)證明原問題總是有一個最優解是做貪心選擇得到的,從而說明貪心選擇是安全的。

3)說明在做出貪心選擇後,剩餘的子問題具有這樣的一個性質。即如果將子問題的最優解和我們所作的貪心選擇聯合起來,可以得出原問題的一個最優解。

貪心選擇性質:一個全域性最優解可以通過區域性最優(貪心)選擇來達到。換句話說,當考慮做如何選擇時,我們只考慮對當前問題的選擇而不考慮子問題的結果。

在動態規劃中,每一步都要做出選擇,但是這些選擇依賴於子問題的解。因此,解動態規劃問題一般是自底向上,從小子問題處理至大子問題。在貪心演算法中,我們所做的總是當前看似最佳的選擇,然後再解決選擇之後的所出現的子問題。貪心演算法所作的當前選擇可能要依賴與已經作出的選擇,但不依賴於有待於做出的選擇或子問題的解,因此貪心策略通常是自頂向下地做的,一個一個地做出貪心選擇,不斷地將給定的問題例項歸約為更小的問題。

最優子結構:對一個問題來說,如果它的一個最優解包含了其子問題的最優解,則稱該問題具有最優子結構。

例7.1 部分揹包問題

描述:把一系列的物品放入總量限制的包裡,要求價值最大。但是物品可以分割為一部分。

8、回溯法

回溯法也稱試探法,它的基本思想是:從問題的某一種狀態(初始狀態)出發,搜尋從這種狀態出發所能達到的所有“狀態”,當一條路走到“盡頭”的時候(不能再前進),再後退一步或若干步,從另一種可能“狀態”出發,繼續搜尋,直到所有的“路徑”(狀態)都試探過。這種不斷“前進”、不斷“回溯”尋找解的方法,就稱作“回溯法”。

用回溯演算法解決問題的一般步驟為:   一、定義一個解空間,它包含問題的解。   二、利用適於搜尋的方法組織解空間。

  三、利用深度優先法搜尋解空間。

四、利用限界函式避免移動到不可能產生解的子空間。問題的解空間通常是在搜尋問題的解的過程中動態產生的,這是回溯演算法的一個重要特性

回溯法是一個既帶有系統性又帶有跳躍性的的搜尋演算法。它在包含問題的所有解的解空間樹中,按照深度優先的策略,從根結點出發搜尋解空間樹。演算法搜尋至解空間樹的任一結點時,總是先判斷該結點是否肯定不包含問題的解。如果肯定不包含,則跳過對以該結點為根的子樹的系統搜尋,逐層向其祖先結點回溯。否則,進入該子樹,繼續按深度優先的策略進行搜尋。回溯法在用來求問題的所有解時,要回溯到根,且根結點的所有子樹都已被搜尋遍才結束。而回溯法在用來求問題的任一解時,只要搜尋到問題的一個解就可以結束。這種以深度優先的方式系統地搜尋問題的解的演算法稱為回溯法,它適用於解一些組合數較大的問題。

9、分支限界法

分支限界 (branch and bound) 演算法是一種在問題的解空間樹上搜索問題的解的方法。但與回溯演算法不同,分支定界演算法採用廣度優先或最小耗費優先的方法搜尋解空間樹,並且,在分支定界演算法中,每一個活結點只有一次機會成為擴充套件結點。利用分支定界演算法對問題的解空間樹進行搜尋,它的搜尋策略是:

1 .產生當前擴充套件結點的所有孩子結點;

2 .在產生的孩子結點中,拋棄那些不可能產生可行解(或最優解)的結點;

3 .將其餘的孩子結點加入活結點表;

4 .從活結點表中選擇下一個活結點作為新的擴充套件結點。如此迴圈,直到找到問題的可行解(最優解)或活結點表為空。

分支限界法的思想是:首先確定目標值的上下界,邊搜尋邊減掉搜尋樹的某些支,提高搜尋效率

例9.1 旅行商問題

問題描述:給定n個城市,有一個旅行商從某一城市出發,訪問每個城市各一次後再回到原出發城市,要求找出的巡迴路徑最短。