one-file-projects/dijkstra.c
2016-01-19 18:28:02 +01:00

139 lines
4.1 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct sAdjElement* AdjList;
struct sAdjElement {
unsigned int nodeto;
float weight;
AdjList next;
};
struct Graph {
AdjList* edges;
unsigned int node_count;
};
struct Graph* graph_create(unsigned int node_count) {
struct Graph* graph = (struct Graph*)malloc(sizeof(struct Graph));
graph->edges = (AdjList*) malloc(node_count * sizeof(AdjList));
graph->node_count = node_count;
for(unsigned int i = 0; i < node_count; i++) graph->edges[i] = NULL;
return graph;
}
void graph_add_edge(struct Graph* graph, unsigned int nodefrom, unsigned int nodeto, float weight) {
if(graph->edges[nodefrom] == NULL) {
AdjList element = malloc(sizeof(struct sAdjElement));
element->nodeto = nodeto;
element->weight = weight;
element->next = NULL;
graph->edges[nodefrom] = element;
} else if(graph->edges[nodefrom]->weight < weight) {
AdjList element = malloc(sizeof(struct sAdjElement));
element->nodeto = nodeto;
element->weight = weight;
element->next = graph->edges[nodefrom];
graph->edges[nodefrom] = element;
} else {
AdjList element = graph->edges[nodefrom];
while(element->nodeto != nodeto && element->next != NULL && element->weight > weight) element = element->next;
if(element->nodeto != nodeto) {
AdjList newelement = malloc(sizeof(struct sAdjElement));
newelement->nodeto = nodeto;
newelement->weight = weight;
newelement->next = element->next;
element->next = newelement;
}
}
}
AdjList graph_get_edges(struct Graph* graph, unsigned int nodefrom) {
return graph->edges[nodefrom];
}
struct Stack {
unsigned int* elements;
unsigned int top;
};
struct Stack* stack_create(unsigned int maxsize) {
struct Stack* newstack = malloc(sizeof(struct Stack));
newstack->elements = malloc(maxsize * sizeof(unsigned int));
return newstack;
}
void stack_destroy(struct Stack* stack) {
free(stack->elements);
free(stack);
}
void stack_push(struct Stack* stack, unsigned int element) {
stack->elements[stack->top++] = element;
}
short stack_contains(struct Stack* stack, unsigned int element) {
for(unsigned int i = 0; i < stack->top; i++) {
if(stack->elements[i] == element) return 1;
}
return 0;
}
unsigned int stack_pop(struct Stack* stack) {
return stack->elements[--stack->top];
}
short stack_empty(struct Stack* stack) {
return stack->top == 0;
}
float* dijkstra(struct Graph* graph, unsigned int startnode) {
struct Stack* stack = stack_create(graph->node_count);
struct Stack* visited = stack_create(graph->node_count);
stack_push(stack,startnode);
float* distances = malloc(graph->node_count * sizeof(float));
for(unsigned int node = 0; node < graph->node_count; node++) {
distances[node] = INFINITY;
}
distances[startnode] = 0;
while(!stack_empty(stack)) {
unsigned int current_node = stack_pop(stack);
printf("Selecting node %d\n", current_node);
stack_push(visited,current_node);
AdjList edge = graph_get_edges(graph, current_node);
while(edge != NULL) {
printf("Edge to node %d\n", edge->nodeto);
if(!stack_contains(visited, edge->nodeto)) {
if(distances[edge->nodeto] > distances[current_node] + edge->weight) {
distances[edge->nodeto] = distances[current_node] + edge->weight;
}
if(!stack_contains(stack,edge->nodeto)) stack_push(stack,edge->nodeto);
}
edge = edge->next;
}
}
stack_destroy(stack);
return distances;
}
int main( int argc, char *argv[] ) {
struct Graph* graph = graph_create(5);
graph_add_edge(graph, 0, 2, 5.0f);
graph_add_edge(graph, 0, 1, 2.0f);
graph_add_edge(graph, 1, 2, 2.0f);
graph_add_edge(graph, 2, 3, 1.0f);
graph_add_edge(graph, 2, 4, 5.0f);
float* distances = dijkstra(graph,0);
for(unsigned int i = 0; i < 5; i++) {
printf("%d: %.2f\n", i, distances[i]);
}
return 0;
}