C Program To Traverse A Multidimensional Array

In addition to 2D arrays, multidimensional arrays can extend to 3D or even higher dimensions. In the scenario of a 3D array, data can be visualized as a series of 2D tables positioned at varying levels akin to a stack. This feature proves beneficial in various applications, such as in 3D images, where there is a necessity to determine the width, height, and depth of certain 3D data. While it is indeed possible to have multidimensional arrays with more than three dimensions, they are not commonly utilized due to the escalating complexity associated with managing such a structure, which becomes increasingly challenging to handle.

Memory Layout

Understanding the memory arrangement of multidimensional arrays is crucial for those interested in optimizing C programming efficiency. In C, multidimensional arrays follow a row-major layout, meaning that the elements within each row of a two-dimensional array are stored contiguously in memory, one after the other. This contrasts with the column-major approach found in certain other programming languages, where elements within each column are stored consecutively.

The elements are ordered in row-major sequence. Initially, the elements in the initial row are positioned first, followed by the elements of the subsequent rows, and then the sequence continues. This indicates that when you access elements in a row in order, it signifies that the memory locations are contiguous, leading to more efficient use of the cache. Modern computer systems are designed with memory caches, and accessing memory locations in a sequential manner can reduce the instances where the processor must fetch frequently used data from the main memory or RAM.

  • As an illustration, let's consider a 2-D array like a matrix. Specifically, in row-major order, all elements of each row are stored in consecutive memory locations, maintaining this pattern for each subsequent row. This organization means that traversing through the array row by row results in linear memory access, which contributes to enhanced performance.
  • Moreover, it aids programmers in understanding potential challenges that may arise when dealing with multidimensional arrays. For example, reading a 2D array by columns instead of rows is inefficient as memory access is not optimized in this manner. Since the elements of a column are not stored sequentially in memory, accessing columns in sequence leads to more cache misses, resulting in slower program execution.
  • Examples:

    1. Basic 2D Array Traversal in C

    Example
    
    #include <stdio.h> 
    
      
    
    int main() { 
    
    // Declare and initialize a 3x4 matrix (2D array) 
    
    int matrix[3][4] = { 
    
    {1, 2, 3, 4}, 
    
    {5, 6, 7, 8}, 
    
    {9, 10, 11, 12} 
    
    }; 
    
      
    
    // Get the number of rows and columns 
    
    int rows = 3; 
    
    int cols = 4; 
    
      
    
    // Traverse the matrix and print each element 
    
        printf("The elements of the matrix are:\n"); 
    
    for (int i = 0; i < rows; i++) { // Loop through each row 
    
    for (int j = 0; j < cols; j++) { // Loop through each column 
    
                printf("%d ", matrix[i][j]); // Print the element at position [i][j] 
    
    } 
    
            printf("\n"); // Move to the next line after printing each row 
    
    } 
    
      
    
    return 0; 
    
    }
    

Output:

Output

The elements of the matrix are: 

1 2 3 4  

5 6 7 8  

9 10 11 12

2. Dynamic 2D Array Traversal

Example

#include <stdio.h> 

#include <stdlib.h> 

  

int main() { 

int rows, cols; 

  

// Ask the user for the number of rows and columns 

    printf("Enter the number of rows: "); 

    scanf("%d", &rows); 

    printf("Enter the number of columns: "); 

    scanf("%d", &cols); 

  

// Dynamically allocate memory for the 2D array 

int** matrix = (int**)malloc(rows * sizeof(int*)); 

for (int i = 0; i < rows; i++) { 

matrix[i] = (int*)malloc(cols * sizeof(int)); 

} 

  

// Fill the matrix with values 

    printf("Enter the elements of the matrix:\n"); 

for (int i = 0; i < rows; i++) { 

for (int j = 0; j < cols; j++) { 

            scanf("%d", &matrix[i][j]); 

} 

} 

  

// Traverse the matrix and print each element 

    printf("The elements of the matrix are:\n"); 

for (int i = 0; i < rows; i++) { 

for (int j = 0; j < cols; j++) { 

            printf("%d ", matrix[i][j]); 

} 

        printf("\n"); 

} 

  

// Deallocate the memory 

for (int i = 0; i < rows; i++) { 

free(matrix[i]); 

} 

free(matrix); 

  

return 0; 

}

Output:

Output

Enter the number of rows: 3 

Enter the number of columns: 4 

Enter the elements of the matrix: 

1 2 3 4 

5 6 7 8 

9 10 11 12 

The elements of the matrix are: 

1 2 3 4 

5 6 7 8 

9 10 11 12

3. Dynamic 3D Array Traversal

Example

#include <stdio.h> 

#include <stdlib.h> 

  

int main() { 

int x, y, z; 

  

// Get dimensions for the 3D array from the user 

    printf("Enter the size of the first dimension (x): "); 

    scanf("%d", &x); 

    printf("Enter the size of the second dimension (y): "); 

    scanf("%d", &y); 

    printf("Enter the size of the third dimension (z): "); 

    scanf("%d", &z); 

  

// Allocate memory for the 3D array 

int ***array = (int ***)malloc(x * sizeof(int **)); 

for (int i = 0; i < x; i++) { 

array[i] = (int **)malloc(y * sizeof(int *)); 

for (int j = 0; j < y; j++) { 

array[i][j] = (int *)malloc(z * sizeof(int)); 

} 

} 

  

// Fill the 3D array with values 

    printf("Enter the elements of the 3D array:\n"); 

for (int i = 0; i < x; i++) { 

for (int j = 0; j < y; j++) { 

for (int k = 0; k < z; k++) { 

                printf("Element at [%d][%d][%d]: ", i, j, k); 

                scanf("%d", &array[i][j][k]); 

} 

} 

} 

  

// Traverse and print the 3D array 

    printf("The elements of the 3D array are:\n"); 

for (int i = 0; i < x; i++) { 

for (int j = 0; j < y; j++) { 

for (int k = 0; k < z; k++) { 

                printf("%d ", array[i][j][k]); 

} 

            printf("\n"); 

} 

        printf("\n"); 

} 

  

// Free the allocated memory 

for (int i = 0; i < x; i++) { 

for (int j = 0; j < y; j++) { 

free(array[i][j]); 

} 

free(array[i]); 

} 

free(array); 

  

return 0; 

}

Output:

Output

Enter the size of the first dimension (x): 2 

Enter the size of the second dimension (y): 2 

Enter the size of the third dimension (z): 2 

Enter the elements of the 3D array: 

Element at [0][0][0]: 1 

Element at [0][0][1]: 2 

Element at [0][1][0]: 3 

Element at [0][1][1]: 4 

Element at [1][0][0]: 5 

Element at [1][0][1]: 6 

Element at [1][1][0]: 7 

Element at [1][1][1]: 8 

The elements of the 3D array are: 

1 2  

3 4  

  

5 6  

7 8

Real-Life Application

Sudoku Solver using Backtracking

Sudoku solving techniques, such as backtracking, have practical applications beyond being just a game. One significant area where these methods are utilized is in Constraint Satisfaction Problems (CSPs), which are prevalent in fields like scheduling, planning, and resource allocation. For instance, when dealing with airline schedules, algorithms similar to Sudoku solving can be employed to assign personnel to flights. This process considers factors such as crew members' work hours compliance, individual availability, and specific qualifications. Below is how this is executed:

Example

#include <stdio.h> 

  

#define UNASSIGNED 0 

#define N 9 

  

// Function to print the Sudoku grid 

void printGrid(int grid[N][N]) { 

for (int row = 0; row < N; row++) { 

for (int col = 0; col < N; col++) { 

            printf("%d ", grid[row][col]); 

} 

        printf("\n"); 

} 

} 

  

// Function to check if a number can be placed in a given cell 

int isSafe(int grid[N][N], int row, int col, int num) { 

// Check the row 

for (int x = 0; x < N; x++) { 

if (grid[row][x] == num) { 

return 0; 

} 

} 

  

// Check the column 

for (int x = 0; x < N; x++) { 

if (grid[x][col] == num) { 

return 0; 

} 

} 

  

// Check the 3x3 subgrid 

int startRow = row - row % 3, startCol = col - col % 3; 

for (int i = 0; i < 3; i++) { 

for (int j = 0; j < 3; j++) { 

if (grid[i + startRow][j + startCol] == num) { 

return 0; 

} 

} 

} 

  

return 1; 

} 

  

// Function to solve the Sudoku puzzle using backtracking 

int solveSudoku(int grid[N][N], int row, int col) { 

// If we have reached the last cell 

if (row == N - 1 && col == N) { 

return 1; 

} 

  

// Move to the next row if we've reached the end of the current row 

if (col == N) { 

row++; 

col = 0; 

} 

  

// If the current cell is already filled, move to the next cell 

if (grid[row][col] != UNASSIGNED) { 

return solveSudoku(grid, row, col + 1); 

} 

  

// Try placing numbers 1-9 in the current cell 

for (int num = 1; num <= 9; num++) { 

if (isSafe(grid, row, col, num)) { 

grid[row][col] = num; 

if (solveSudoku(grid, row, col + 1)) { 

return 1; 

} 

grid[row][col] = UNASSIGNED; // Backtrack 

} 

} 

  

return 0; // Trigger backtracking 

} 

  

int main() { 

// 0 represents an empty cell 

int grid[N][N] = { 

{5, 3, 0, 0, 7, 0, 0, 0, 0}, 

{6, 0, 0, 1, 9, 5, 0, 0, 0}, 

{0, 9, 8, 0, 0, 0, 0, 6, 0}, 

{8, 0, 0, 0, 6, 0, 0, 0, 3}, 

{4, 0, 0, 8, 0, 3, 0, 0, 1}, 

{7, 0, 0, 0, 2, 0, 0, 0, 6}, 

{0, 6, 0, 0, 0, 0, 2, 8, 0}, 

{0, 0, 0, 4, 1, 9, 0, 0, 5}, 

{0, 0, 0, 0, 8, 0, 0, 7, 9} 

}; 

  

if (solveSudoku(grid, 0, 0)) { 

        printf("Solved Sudoku grid:\n"); 

        printGrid(grid); 

} else { 

        printf("No solution exists.\n"); 

} 

  

return 0; 

}

Output:

Output

Solved Sudoku grid: 

5 3 4 6 7 8 9 1 2  

6 7 2 1 9 5 3 4 8  

1 9 8 3 4 2 5 6 7  

8 5 9 7 6 1 4 2 3  

4 2 6 8 5 3 7 9 1  

7 1 3 9 2 4 8 5 6  

9 6 1 5 3 7 2 8 4  

2 8 7 4 1 9 6 3 5  

3 4 5 2 8 6 1 7 9

Conclusion:

In summary, navigating through arrays with multiple dimensions in C is a crucial aspect that opens up numerous possibilities for tackling a wide range of computational challenges. From basic tasks like looping through a 2D array to intricate endeavors like building a Sudoku solver with backtracking, these skills lay the foundation for solving complex programming problems. Efficiently managing multidimensional arrays empowers developers to efficiently process large datasets essential for scientific computations, data interpretation, and live simulations.

It's worth highlighting that these methods are not restricted to academic settings or illustrations, as illustrated below. Whether it's in the realm of digital circuit design, solving equations related to scheduling, managing resources, or delving into bioinformatics, the ability to efficiently handle data structures is an invaluable skill. Understanding these array traversal strategies empowers developers to devise superior, streamlined, and dependable algorithms, which are crucial not just for scholars and researchers but also for implementing cutting-edge computer systems. Consequently, this subject fortifies the foundations of programming, particularly enhancing overall proficiency and readiness for tackling intricate challenges across diverse technological and scientific domains.

Input Required

This code uses input(). Please provide values below: