深度優先搜尋演算法(DFS)講解

Silly_3kidZ發表於2024-03-11

深度優先搜尋演算法(DFS)講解

深度優先搜尋(DFS)是一種用於遍歷或搜尋樹或圖的演算法。它以深入探索圖的分支為目標,直到到達指定的“深度”,無法繼續前進為止,然後透過回溯探索其他分支。DFS是資料結構與演算法中一個非常重要且基礎的概念,對於理解複雜資料結構的搜尋和遍歷過程至關重要。

1. DFS定義及應用

DFS允許你從一個頂點開始,沿著樹或圖的邊走到儘可能深的分支,然後透過回溯,繼續探索未遍歷的分支。它的應用非常廣泛,包括解決迷宮問題、路徑查詢、檢查圖中是否存在環、排序問題等。

2. DFS原理

DFS的核心思想是使用遞迴或棧來實現對圖的深入探索。在遞迴實現中,DFS從一個頂點開始,訪問其任一未被訪問的鄰接頂點,將其標記為已訪問,然後從這個鄰接頂點出發繼續這一過程,形成遞迴。當到達一個頂點而它沒有未訪問的鄰接頂點時,演算法將回溯,繼續探索前一個頂點的其他鄰接頂點。

3. DFS程式碼框架

DFS的程式碼看起來簡單,但是初學者在邏輯上會感到難以理解。請讀者在大量編碼的基礎上,再回頭體會這個框架的作用。

ans
void dfs(層數,其他引數){
    if(出局判斷){ // 到達最底層,或者滿足條件推出
        更新答案 // 答案一般用全域性變數表示
        return; // 返回到上一層
    }
    (搜尋順序剪枝(最佳化搜尋順序) || 最優性剪枝) // 在進一步dfs之前剪枝
    for(列舉下一層可能的情況){
        if(used[i]==0 && 可行性剪枝){ // 如果狀態i沒有用過,就可以進入下一層
            used[i]=1; // 標記狀態i已經使用過 
            dfs(層數+1,其他引數); // 下一層
            used[i]=0; // 回溯
        }
    }
    return; // 返回到上一層
}

4. DFS的優點和缺點

優點:

  • 空間效率高:DFS在實現時可以透過遞迴呼叫的系統棧來儲存資訊,因此它的空間複雜度相對較低。
  • 適用於路徑和配置問題:對於需要尋找所有可能路徑的問題,DFS提供了一種直接而有效的解決方案。

缺點:

  • 時間複雜度可能高:在最壞的情況下,需要訪問所有的頂點和邊,時間複雜度為O(V+E),其中V是頂點數,E是邊數。
  • 可能不會找到最短路徑:對於需要找到最短路徑的問題,DFS可能不是最好的選擇。

5.回溯及其使用與避免

回溯的概念及其在DFS中的角色

回溯可以被看作是DFS的一個特例或者說是一種策略,它的核心思想是“走不通就退回去”。簡單來說,當DFS在探索過程中遇到一個死路(即沒有其他出路或者沒有達到目標條件的路)時,它就會沿著來時的路徑退回一步,嘗試其他的可能性。

使用回溯解決問題的情況

回溯法非常適合解決需要多次嘗試、尋找所有可能解的問題。例如,解謎題(如八皇后問題)、組合問題(如數獨)等,都是透過嘗試每一種可能的組合來找到解決方案。在這些問題中,每做出一個選擇,就進入下一層決策樹;如果發現當前選擇導致無法達到目標,就退回到上一層,改變選擇。

判斷是否使用回溯及其限制

在實施DFS時,如果問題需要遍歷所有可能的路徑來找到解決方案,或者需要不斷嘗試直到滿足特定條件,那麼使用回溯是非常合適的。

回溯避免示例

在解決洪水填充這一類連通性相關的問題當中,我們要避免使用回溯;我們可以從以下兩個角度去理解:

  1. 在解決這一類連通性問題中,我們不需要多次嘗試、尋找所有可能解,就像遍歷一棵樹/圖一樣,只需簡單的進行dfs遍歷即可,不需要回溯
  2. 呼叫使用了回溯的dfs函式後,所有狀態都會迴歸初始狀態,而解決連通性這一類問題中我們需要呼叫dfs後所有連通塊中的狀態都被更新,因此我們要避免使用回溯

DFS剪枝最佳化

深度優先搜尋(DFS)是一種遍歷或搜尋樹或圖的演算法,它從一個根節點開始,儘可能深地搜尋每個分支,直到找到解為止。在搜尋過程中,為了提高效率,減少不必要的搜尋,通常會採用各種剪枝最佳化策略。下面詳細介紹幾種常用的DFS剪枝最佳化策略:

1. 最佳化搜尋順序

  • 目的:透過調整搜尋順序,使得搜尋儘快地接近目標或者儘早地剪枝。
  • 策略:在開始搜尋前,對所有可能的選擇進行排序,優先搜尋那些最有可能導致最優解或最快發現無解(以便剪枝)的選項。例如,在解決揹包問題時,可以先考慮價值密度最高的物品。

2. 排除等效冗餘

  • 目的:避免搜尋到重複或等效的解,減少搜尋空間。
  • 策略:在搜尋過程中,如果發現當前的選擇會導致之前已經搜尋過的狀態,則可以直接剪枝。例如,在全排列問題中,如果某個數已經被選取,那麼在這一層的其他分支中就不再考慮這個數。

3. 可行性剪枝

  • 目的:在搜尋過程中,一旦發現當前路徑不可能達到目標(即不可行),立即停止進一步搜尋。
  • 策略:根據問題的約束條件,實時計算當前選擇的後果,如果違反約束則立即回溯。例如,在求解和為特定值的子集問題中,如果當前子集的和已經超過目標值,就可以停止向該分支的更深層搜尋。

4. 最最佳化剪枝

  • 目的:在搜尋過程中,及早排除那些即使在最好情況下也比已找到的最優解差的路徑。
  • 策略:維護一個全域性的最優解變數,在搜尋過程中,如果某個分支的最佳可能結果仍然不如當前最優解,則放棄該分支。例如,在旅行商問題(TSP)中,如果當前路徑加上未訪問城市的最小成本估算仍然大於當前最短路徑,則放棄該路徑。

總結

一道題目中可能用到多種剪枝技術,不過用不著可以區分是哪種剪枝技術,總體思路就是減少搜尋狀態。

相關文章