使用深度優先搜尋 (DFS) 遍歷列印矩陣元素


介紹

深度優先搜尋 (DFS) 是一種圖遍歷方法,它透過從特定節點開始,儘可能沿著每個分支向下遍歷,直到無法繼續為止,然後再回溯到其他分支。它關注圖的“深度”,從最深的節點開始,然後回溯檢視其他分支。DFS 可以使用遞迴或棧來實現。它可以用於查詢路徑、查詢圖和向量中的迴圈以及進行窮舉搜尋。

理解矩陣結構

在資料分析中,矩陣是一個二維陣列。在計算機程式設計中,矩陣資料可以以多種方式儲存,包括陣列、列表的列表以及其他特定的資料結構。矩陣元素在遍歷和操作期間的可訪問性取決於它們是在記憶體中按行優先順序還是按列優先順序儲存的。行優先順序是指將行中的元素按順序儲存,而列優先順序是指將列中的元素按順序儲存。使用正確的表示方法可以使矩陣操作更高效。

深度優先搜尋演算法

DFS(深度優先搜尋)是一種圖遍歷方法,它儘可能沿著每個分支向下遍歷,然後再回溯到其他分支。

  • 遞迴 DFS -

  • 遞迴 DFS 是實現 DFS 最簡單、最直觀的方法。它使用函式遞迴來遍歷圖或矩陣。演算法的工作原理如下:

    • 選擇一個起始節點或元素作為當前位置。

    • 將當前節點/元素標記為已訪問,以避免迴圈。

    • 遞迴地探索當前節點/元素的每個未訪問的鄰居,方法是使用鄰居作為新的當前位置呼叫 DFS 函式。

    • 如果所有鄰居都已訪問或沒有未訪問的鄰居,則回溯。

  • 使用棧的迭代 DFS -

  • 為了避免潛在的棧溢位問題,可以使用迭代方法來實現 DFS。此方法使用顯式棧資料結構來跟蹤要訪問的節點或元素。演算法的工作原理如下:

    • 初始化一個空棧,並將起始節點或元素壓入棧中。

    • 當棧 != 0 時 -

    • 從棧中彈出頂部元素,並將其標記為已訪問。

    • 探索當前元素的所有未訪問鄰居,並將它們壓入棧中。

    • 重複步驟 a 和 b,直到所有鄰居都被訪問或棧為空。

  • 時間複雜度:遞迴和迭代 DFS 的時間複雜度均為 O(V + E),其中 V 表示圖或矩陣中的頂點(節點),E 表示邊(連線)。

  • 空間複雜度:由於隱式函式呼叫棧,遞迴 DFS 的空間複雜度為 O(V),而迭代 DFS 使用顯式棧儲存最多 V 個頂點,其空間複雜度為 O(V)。

實現用於矩陣遍歷的 DFS

  • 選擇起始點:在矩陣中選擇一個有效的起始單元格來開始 DFS 遍歷。

  • 初始化資料結構:建立一個二維布林陣列來跟蹤遍歷期間已訪問的單元格。

  • 處理邊界條件:確保演算法在探索相鄰單元格時保持在矩陣邊界內。

  • 防止迴圈:將單元格標記為已訪問,以避免重新訪問它們並防止無限迴圈。

防止迴圈:將單元格標記為已訪問,以避免重新訪問它們並防止無限迴圈。

使用 DFS 列印矩陣元素

  • 使用 DFS 遍歷探索矩陣:DFS 遍歷可以系統地探索矩陣,從選擇的入口點開始,沿著一條路徑儘可能遠地遍歷,然後再回溯。起始點可能會影響元素訪問的順序。

  • 在 DFS 遍歷期間列印元素:在 DFS 中,我們可以打印出每個已訪問的矩陣元素。這使我們能夠系統地檢視和檢查矩陣。

  • 回溯及其在 DFS 中的重要性:回溯在 DFS 中很重要,因為它可以阻止無限迴圈並確保覆蓋每個部分。它使 DFS 能夠遍歷不連通或稀疏的矩陣,確保完全探索整個矩陣。

Java 示例實現

import java.util.Stack;
public class Matrix {
   private int[][] data;
   private int numRows;
   private int numCols;
   public Matrix(int numRows, int numCols) {
      this.numRows = numRows;
      this.numCols = numCols;
      this.data = new int[numRows][numCols];
   }
   public void dfsRecursive(int row, int col, boolean[][] visited) {
      if (row < 0 || col < 0 || row >= numRows || col >= numCols || visited[row][col]) {
         return;
      }
   visited[row][col] = true;
   System.out.print(data[row][col] + " ");
   
   dfsRecursive(row - 1, col, visited); // Up
   dfsRecursive(row + 1, col, visited); // Down
   dfsRecursive(row, col - 1, visited); // Left
   dfsRecursive(row, col + 1, visited); // Right
   }
   public void dfsIterative(int startRow, int startCol) {
      boolean[][] visited = new boolean[numRows][numCols];
      Stack<int[]> stack = new Stack<>();
      
   stack.push(new int[]{startRow, startCol});
   while (!stack.isEmpty()) {
      int[] current = stack.pop();
      int row = current[0];
      int col = current[1];
      
      if (row < 0 || col < 0 || row >= numRows || col >= numCols || visited[row][col]) {
         continue;
   }
      visited[row][col] = true;
      System.out.print(data[row][col] + " ");
      
      stack.push(new int[]{row - 1, col}); // Up
      stack.push(new int[]{row + 1, col}); // Down
      stack.push(new int[]{row, col - 1}); // Left
      stack.push(new int[]{row, col + 1}); // Right
      }
   }
   public static void main(String[] args) {
      int[][] exampleMatrix = {
         {1, 2, 3},
         {4, 5, 6},
         {7, 8, 9}
      };
      Matrix matrix = new Matrix(3, 3);
      matrix.data = exampleMatrix;
      
      int startRow = 0;
      int startCol = 0;
      
      System.out.println("Recursive DFS traversal:");
      matrix.dfsRecursive(startRow, startCol, new
      boolean[matrix.numRows][matrix.numCols]);
      
      System.out.println("\nIterative DFS traversal:");
      matrix.dfsIterative(startRow, startCol);
   }
}

輸出

Recursive DFS traversal:
1 4 7 8 5 2 3 6 9 
Iterative DFS traversal:
1 2 3 6 5 4 7 8 9 

比較 DFS 與 BFS 矩陣遍歷

用於矩陣遍歷的 DFS

  • DFS 沿著每個分支儘可能遠地遍歷,然後再回溯。

  • 它可能無法保證最短路徑,並且可能陷入迴圈。

  • 使用遞迴或顯式棧實現;比 BFS 更節省記憶體。

  • 適用於窮舉探索和解決謎題/迷宮。

用於矩陣遍歷的 BFS

  • BFS 首先探索直接鄰居,然後再移動到下一個深度級別。

  • 它保證在非加權圖或矩陣中找到最短路徑。

  • BFS 使用佇列資料結構,需要更多記憶體來儲存每個級別的節點。

  • 非常適合查詢連通分量並逐層探索。

結論

總而言之,深度優先搜尋 (DFS) 是一種有效的探索矩陣元素的方法。其遞迴和迭代實現使其易於探索和列印矩陣元素。DFS 可用於分析圖、處理影像和解決謎題,使其成為許多現實世界應用中的一種有用工具。

更新於:2023年7月28日

555 次瀏覽

開啟你的職業生涯

完成課程獲得認證

開始學習
廣告
© . All rights reserved.