Print matrix elements using DFS traversal


Introduction

Depth-First Search (DFS) is a graph traversal method that looks at vertices and edges by starting at a certain node and going as far as possible down each branch before going back.It looks at the "depth" of the graph, starting with the node that is the deepest and then going back to look at other lines. Recursion or a stack can be used to make DFS work. It can be used to find paths, find cycles in graphs and vectors, and do exhaustive searches.

Understanding the Matrix Structure

In data analysis, a matrix is a two-dimensional array. Matrix data can be stored in a variety of ways in computer programming, including arrays, lists of lists, and other specific data structures. How elements of a matrix are accessible during traversal and operations depends on whether they are stored in memory with row-major order or column-major order. Elements in a row are kept in sequential order when using row-major order, whereas columns are kept in sequential order when using column-major order. Matrix operations are most effective when the correct representation is used.

The Depth-First-Search Algorithm

DFS, or "Depth-First Search," is a graph traversal method that goes as far as possible along each branch before going back to explore other branches.

  • Recursive DFS −

  • Recursive DFS is the simplest and most intuitive way to implement DFS. It uses function recursion to traverse through the graph or matrix. The algorithm works as follows:

    • Choose a starting node or element as the current position.

    • Mark the current node/element as visited to avoid cycles.

    • Explore each unvisited neighbor of the current node/element recursively by calling the DFS function with the neighbor as the new current position

    • Backtrack if all neighbors have been visited or if there are no unvisited neighbors.

  • Iterative DFS using a stack −

  • To avoid potential stack overflow issues, an iterative approach can be used to implement DFS. This approach uses an explicit stack data structure to keep track of nodes or elements to be visited. The algorithm works as follows −

    • Initialize an empty stack and push the starting node or element onto the stack.

    • While the stack =! 0 −

    • Pop the top element from the stack and mark it as visited.

    • Explore all unvisited neighbors of the current element, pushing them onto the stack.

    • Repeat steps a and b until all neighbors are visited or the stack becomes empty.

  • Time Complexity: Both recursive and iterative DFS have O(V + E) time complexity,where V represents vertices (nodes) and E are the edges (connections) in the graph or matrix.

  • Space Complexity: Recursive DFS has O(V) space complexity due to the implicit function call stack, while iterative DFS has O(V) space complexity with an explicit stack for storing at most V vertices.

Implementing DFS for Matrix Traversal

  • Selecting the Starting Point: Choose a valid starting cell within the matrix to begin the DFS traversal

  • Initializing Data Structures: Create a 2D boolean array to track visited cells during traversal

  • Handling Boundary Conditions: Ensure the algorithm stays within matrix bounds while exploring neighboring cells

  • Preventing Cycles: Mark cells as visited to avoid revisiting them and prevent infinite loops.

Preventing Cycles: Mark cells as visited to avoid revisiting them and prevent infinite loops.

Printing Matrix Elements Using DFS

  • Exploring the Matrix Using DFS Traversal: DFS traversal enables systematic exploration of a matrix, starting from a chosen entry point and following a path as far as possible before backtracking. The starting point may impact the order of element visits.

  • Printing Elements During DFS Traversal: In DFS, we can print out each element of the matrix as it is visited. This lets us look at and examine the matrix in a systematic way

  • Backtracking and Its Significance in DFS: Backtracking is important in DFS because it stops endless loops and makes sure that every part is covered. It lets DFS move through disconnected or sparse matrices, making sure that the whole matrix is fully explored.

Example Implementation in 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);
   }
}

Output

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

Comparing DFS with BFS Matrix Traversal

DFS for Matrix Traversal

  • DFS follows each branch as far as it can go before turning around

  • It may not guarantee the shortest path and can get stuck in cycles

  • Implemented using recursion or an explicit stack; more memory-efficient than BFS

  • Suitable for exhaustive exploration and solving puzzles/mazes

BFS for Matrix Traversal

  • BFS explores immediate neighbors first before moving to the next depth level

  • It guarantees finding the shortest path in an unweighted graph or matrix

  • BFS uses a queue data structure and requires more memory to store nodes at each level.

  • Ideal for finding connected components and exploring level by level.

Conclusion

In conclusion, Depth-First Search (DFS) search is an effective way to look at the parts of a matrix. Its implementations of recursion and iteration make it easy to explore and print matrix parts. DFS can be used to analyze graphs, process images, and solve puzzles, making it a useful tool for many real-world situations

Someswar Pal
Someswar Pal

Studying Mtech/ AI- ML

Updated on: 28-Jul-2023

219 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements