addtition: dijkstra
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
#ifndef GRAPH_H
|
#ifndef GRAPH_H
|
||||||
#define GRAPH_H
|
#define GRAPH_H
|
||||||
|
|
||||||
|
#include "arraylist.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
typedef struct Graph Graph;
|
typedef struct Graph Graph;
|
||||||
@@ -12,6 +13,7 @@ typedef enum {
|
|||||||
GRAPH_BAD_ALLOC,
|
GRAPH_BAD_ALLOC,
|
||||||
GRAPH_VERTEX_NOT_FOUND,
|
GRAPH_VERTEX_NOT_FOUND,
|
||||||
GRAPH_NULL_ARG,
|
GRAPH_NULL_ARG,
|
||||||
|
GRAPH_EMPTY,
|
||||||
} GraphErr ;
|
} GraphErr ;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -19,6 +21,11 @@ typedef enum {
|
|||||||
GRAPH_UNDIRECTED,
|
GRAPH_UNDIRECTED,
|
||||||
} GraphType;
|
} GraphType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ArrayList *distances;
|
||||||
|
ArrayList *prev;
|
||||||
|
} DijkstraResult;
|
||||||
|
|
||||||
Graph *graph_create(GraphType type);
|
Graph *graph_create(GraphType type);
|
||||||
GraphErr graph_destroy(Graph **graph);
|
GraphErr graph_destroy(Graph **graph);
|
||||||
|
|
||||||
@@ -32,5 +39,6 @@ GraphErr graph_connect_vertex(
|
|||||||
|
|
||||||
GraphErr graph_vertex_count(Graph *graph, size_t *out);
|
GraphErr graph_vertex_count(Graph *graph, size_t *out);
|
||||||
GraphErr graph_get_vertex(Graph *graph, size_t index, Vertex *out);
|
GraphErr graph_get_vertex(Graph *graph, size_t index, Vertex *out);
|
||||||
|
GraphErr graph_dijkstra(Graph *graph, size_t source, DijkstraResult *result);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
84
src/graph.c
84
src/graph.c
@@ -1,10 +1,10 @@
|
|||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
#include "arraylist.h"
|
#include "arraylist.h"
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/ucontext.h>
|
|
||||||
|
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
ArrayList *edges;
|
ArrayList *edges;
|
||||||
@@ -122,3 +122,85 @@ GraphErr graph_get_vertex(Graph *graph, size_t index, Vertex *out) {
|
|||||||
|
|
||||||
return GRAPH_OK;
|
return GRAPH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GraphErr graph_dijkstra(Graph *graph, size_t source, DijkstraResult *result) {
|
||||||
|
if (graph == NULL || result == NULL) {
|
||||||
|
return GRAPH_NULL_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source >= arraylist_size(graph->vertices)) {
|
||||||
|
return GRAPH_VERTEX_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arraylist_size(graph->vertices) == 0) {
|
||||||
|
return GRAPH_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t vertex_count = arraylist_size(graph->vertices);
|
||||||
|
|
||||||
|
ArrayList *distances = arraylist_init(vertex_count, sizeof(size_t));
|
||||||
|
ArrayList *visited = arraylist_init(vertex_count, sizeof(bool));
|
||||||
|
ArrayList *prev = arraylist_init(vertex_count, sizeof(size_t));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < vertex_count; i++) {
|
||||||
|
arraylist_push_back(distances, SIZE_MAX);
|
||||||
|
arraylist_push_back(visited, false);
|
||||||
|
arraylist_push_back(prev, SIZE_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
arraylist_set(distances, source, &(size_t){0});
|
||||||
|
|
||||||
|
for (size_t i = 0; i < vertex_count; i++) {
|
||||||
|
|
||||||
|
size_t current = SIZE_MAX;
|
||||||
|
size_t min_dist = SIZE_MAX;
|
||||||
|
|
||||||
|
for (size_t j = 0; j < vertex_count; j++) {
|
||||||
|
bool is_visited;
|
||||||
|
size_t dist;
|
||||||
|
|
||||||
|
arraylist_get(visited, j, &is_visited);
|
||||||
|
arraylist_get(distances, j, &dist);
|
||||||
|
|
||||||
|
if (!is_visited && dist < min_dist) {
|
||||||
|
min_dist = dist;
|
||||||
|
current = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current == SIZE_MAX) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
arraylist_set(visited, current, &(bool){true});
|
||||||
|
|
||||||
|
Vertex vertex;
|
||||||
|
graph_get_vertex(graph, current, &vertex);
|
||||||
|
|
||||||
|
for (size_t j = 0; j < arraylist_size(vertex.edges); j++) {
|
||||||
|
|
||||||
|
Edge current_edge;
|
||||||
|
arraylist_get(vertex.edges, j, ¤t_edge);
|
||||||
|
|
||||||
|
size_t current_dist;
|
||||||
|
arraylist_get(distances, current, ¤t_dist);
|
||||||
|
if (current_dist == SIZE_MAX) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t new_dist = current_dist + current_edge.weight;
|
||||||
|
|
||||||
|
size_t to_dist;
|
||||||
|
arraylist_get(distances, current_edge.to, &to_dist);
|
||||||
|
if (new_dist < to_dist) {
|
||||||
|
arraylist_set(distances, current_edge.to, &new_dist);
|
||||||
|
arraylist_set(prev, current_edge.to, ¤t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arraylist_destroy(&visited);
|
||||||
|
*result = (DijkstraResult){.distances = distances, .prev = prev};
|
||||||
|
|
||||||
|
return GRAPH_OK;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user