← index
graph/matrix.c
Source: C2x.Examples/src/graph/matrix.c
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

static const int INFINITE = 1e9;

typedef struct {
    int *matrix;
    size_t num;
} Matrix;

enum {
    NO_EDGE = -1,
    EDGE = 1
};

#define ADD_EDGE(mat, from, to, weight)           \
    if (!add_edge(&mat, from, to, weight, false)) \
        return EXIT_FAILURE;

bool init_matrix(Matrix *matrix, size_t num) {
    if (matrix == nullptr || num == 0)
        return false;
    matrix->num = num;
    size_t sizeval = ((num * num) * sizeof(int));
    int *mat = malloc(sizeval);
    if (mat == nullptr)
        return false;
    matrix->matrix = mat;
    for (size_t i = 0; i < (num * num); ++i) {
        matrix->matrix[i] = NO_EDGE;
    }
    for (size_t i = 0; i < num; ++i) {
        matrix->matrix[i * num + i] = 0;
    }
    return true;
}

void free_matrix(Matrix *matrix) {
    if (matrix == nullptr)
        return;
    free(matrix->matrix);
}

bool add_edge(Matrix *matrix, size_t from, size_t to, int weight, bool directed) {
    if (matrix == nullptr || matrix->matrix == nullptr)
        return false;
    if (from >= matrix->num || to >= matrix->num) {
        fprintf(stderr, "Index out of range.\n");
        return false;
    }
    matrix->matrix[from * matrix->num + to] = weight;
    if (!directed) {
        matrix->matrix[to * matrix->num + from] = weight;
    }
    return true;
}

int get_weight(const Matrix *matrix, size_t from, size_t to) {
    if (matrix == nullptr || matrix->matrix == nullptr)
        return false;

    return matrix->matrix[from * matrix->num + to];
}

void print(Matrix *matrix) {
    if (matrix == nullptr || matrix->matrix == nullptr)
        return;
    printf("    ");
    for (size_t i = 0; i < matrix->num; ++i) {
        printf("%4zu ", i);
    }
    printf("\n");
    for (size_t i = 0; i < matrix->num; ++i) {
        printf("%2zu |", i);
        for (size_t z = 0; z < matrix->num; ++z) {
            int w = get_weight(matrix, i, z);
            if (w == NO_EDGE) {
                printf("   - ");
            } else {
                printf("%4d ", w);
            }
        }
        printf("\n");
    }
}

bool dijkstra_matrix(const Matrix *graph, int start, int destination) {
    if (graph == nullptr || graph->matrix == nullptr || start < 0 || (size_t)start >= graph->num || destination < 0 || (size_t)destination >= graph->num) {
        fprintf(stderr, "Invalid graph dimensions or target.\n");
        return false;
    }
    size_t num = graph->num;
    int *dist = malloc(num * sizeof(int));
    int *prev = malloc(num * sizeof(int));
    bool *visited = malloc(num * sizeof(bool));
    if (dist == nullptr || prev == nullptr || visited == nullptr) {
        free(dist);
        free(prev);
        free(visited);
        return false;
    }
    for (size_t i = 0; i < num; ++i) {
        dist[i] = INFINITE;
        prev[i] = -1;
        visited[i] = false;
    }
    dist[start] = 0;
    for (size_t count = 0; count < num; ++count) {
        int min_dist = INFINITE;
        int u = -1;
        for (size_t i = 0; i < num; ++i) {
            if (!visited[i] && dist[i] <= min_dist) {
                min_dist = dist[i];
                u = (int)i;
            }
        }
        if (u == -1 || min_dist == INFINITE) {
            break;
        }
        visited[u] = true;
        for (size_t v = 0; v < num; ++v) {
            int weight = get_weight(graph, (size_t)u, v);
            if (!visited[v] && weight != NO_EDGE && dist[u] + weight < dist[v]) {
                dist[v] = dist[u] + weight;
                prev[v] = u;
            }
        }
    }
    if (dist[destination] == INFINITE) {
        printf("No path exists from %d to %d\n", start, destination);
    } else {
        printf("Path to %d:\n", destination);
        int current = destination;
        while (current != -1) {
            printf("%d ", current);
            current = prev[current];
        }
        printf("\nTotal distance: %d\n", dist[destination]);
    }
    free(dist);
    free(prev);
    free(visited);
    return true;
}

bool generate_test_matrix(Matrix *mat, size_t num, unsigned int seed) {
    srand(seed);
    if (!init_matrix(mat, num)) {
        return false;
    }
    for (size_t i = 0; i < num; ++i) {
        if (i < num - 1) {
            add_edge(mat, i, i + 1, (rand() % 10) + 1, false);
        }
        int extra_edges = rand() % 3;
        for (int j = 0; j < extra_edges; ++j) {
            size_t target = (size_t)rand() % num;
            if (target != i) {
                int weight = (rand() % 20) + 1;
                add_edge(mat, i, target, weight, false);
            }
        }
    }
    return true;
}

int main(void) {
    size_t node_count = 50;
    int start_node = 0;
    int target_node = 49;
    Matrix mat;
    if (!generate_test_matrix(&mat, node_count, (unsigned int)time(nullptr))) {
        fprintf(stderr, "Failed to generate test matrix.\n");
        return EXIT_FAILURE;
    }
    if (!dijkstra_matrix(&mat, start_node, target_node)) {
        fprintf(stderr, "Error dijkstra algorithm failed.\n");
        free_matrix(&mat);
        return EXIT_FAILURE;
    }
    print(&mat);
    free_matrix(&mat);
    return EXIT_SUCCESS;
}