Commit 9bb3d3ae authored by Paffenholz, Andreas's avatar Paffenholz, Andreas

programs ch 15, Dijkstra

parent c31079ce
/*************************************
* Beispielprogramm zur Vorlesung
* Einfuehrung in die Programmierung I
* Andreas Paffenholz
* TU Darmstadt, Wintersemester 2020/21
* (c) 2020-
*
* Kürzeste Wege in Netzwerken
**************************************/
#include "dijkstra.h"
void dijkstra (struct network * g, int start) {
struct heap * h = init_heap(3, g->n_nodes);
int * heap_index = (int *)malloc(g->n_nodes * sizeof(int));
for ( int i = 0; i < g->n_nodes; ++i) {
heap_index[i] = 0;
}
push(h, heap_index, start, 0);
g->nodes[start]->pred=-1;
g->nodes[start]->dist=0;
while (h->length) {
int node_index = pop(h, heap_index);
struct node * node = g->nodes[node_index];
node->visited = 1;
for (int j = 0; j < node->n_outgoing_edges; j++) {
struct edge * e = node->outgoing_edges[j];
struct node * neighbor = g->nodes[e->head];
if (!neighbor->visited && node->dist + e->weight <= neighbor->dist) {
neighbor->pred = node_index;
neighbor->dist = node->dist + e->weight;
if ( heap_index[e->head] == 0 )
push(h, heap_index, e->head, neighbor->dist);
else
decrease_key(h, heap_index, e->head, neighbor->dist);
}
}
}
free(heap_index);
free_heap(h);
}
void predecessors(struct network * g, int * pred) {
for ( int i = 0; i < g->n_nodes; ++i ) {
pred[i] = g->nodes[i]->pred;
}
}
/*************************************
* Beispielprogramm zur Vorlesung
* Einfuehrung in die Programmierung I
* Andreas Paffenholz
* TU Darmstadt, Wintersemester 2020/21
* (c) 2020-
*
* Kürzeste Wege in Netzwerken, Header
**************************************/
#ifndef DIJKSTRA_H
#define DIJKSTRA_H
#include "stdio.h"
#include "stdlib.h"
#include "limits.h"
#include "network.h"
#include "heap.h"
void dijkstra (struct network *, int);
void predecessors(struct network *, int *);
#endif
\ No newline at end of file
/*************************************
* Beispielprogramm zur Vorlesung
* Einfuehrung in die Programmierung I
* Andreas Paffenholz
* TU Darmstadt, Wintersemester 2020/21
* (c) 2020-
*
* Kürzeste Wege in Netzwerken, Testprogramm
*
* Uebersetzen mit
* gcc dijkstra_main.c dijkstra.c network.c heap.c -o dijkstra
* Aufruf mit
* ./dijkstra in_network 0
**************************************/
#include <stdio.h>
#include <stdlib.h>
#include "network.h"
#include "dijkstra.h"
int main(int argc, char** argv) {
if ( argc < 2 ) {
fprintf(stderr, "Netwerk und Startknoten muessen angegeben werden\n");
exit(1);
}
char * infile = argv[1];
int start = atoi(argv[2]);
struct network * g = read_network(infile);
dijkstra(g,start);
printf("The nodes have distance \n");
for ( int i = 0; i < g->n_nodes; ++i ) {
printf("%d: %d\n", i, g->nodes[i]->dist);
}
int * pred = (int *)malloc(g->n_nodes * sizeof(int));
predecessors(g,pred);
printf("The shortest path tree is given by the edges\n");
for ( int i = 0; i < g->n_nodes; ++i ) {
if ( pred[i] != -1 ) {
printf("(%d, %d)\n", pred[i],i);
}
}
free(pred);
free_network(g);
return 0;
}
\ No newline at end of file
/*************************************
* Beispielprogramm zur Vorlesung
* Einfuehrung in die Programmierung I
* Andreas Paffenholz
* TU Darmstadt, Wintersemester 2020/21
* (c) 2020-
*
* Priority Queue als Heap
**************************************/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "heap.h"
struct heap * init_heap (int n, int index_size) {
struct heap * h = (struct heap *)malloc(sizeof (struct heap));
h->data = (int *)malloc((n+1) * sizeof (int));
h->key = (int *)malloc((n+1) * sizeof (int));
h->size = n;
h->length = 0;
return h;
}
void free_heap(struct heap * h) {
free(h->data);
free(h->key);
free(h);
}
void resize_heap ( struct heap * h) {
int new_size = h->size *3 / 2 >= h->length ? h->size *3 / 2 : h->size + 3;
h->data = realloc(h->data, (new_size) * sizeof(int) );
h->key = realloc(h->key, (new_size) * sizeof(int) );
h->size = new_size;
}
void print_heap(struct heap * h) {
printf("current heap (entries as (node, key)): ");
for ( int i = 0; i < h->length; ++i) {
printf("(%d, %d) ", h->data[i], h->key[i]);
}
printf("\n");
}
int upheap ( struct heap * h, int * heap_index, int i, int key ) {
int j = (i-1) / 2 ;
while (i > 0) {
if (h->key[j] < key)
break;
h->data[i] = h->data[j];
h->key[i] = h->key[j];
heap_index[h->data[i]] = i;
i = j;
j = (j-1) / 2;
}
return i;
}
void decrease_key (struct heap * h, int * heap_index, int node, int key ) {
int insert_pos = upheap(h, heap_index, heap_index[node], key);
h->data[insert_pos] = node;
h->key[insert_pos ] = key;
heap_index[node] = insert_pos;
}
void push (struct heap * h, int * heap_index, int node, int key ) {
if ( h->size <= h->length )
resize_heap(h);
int insert_pos = upheap(h, heap_index, h->length++, key);
h->data[insert_pos] = node;
h->key[insert_pos ] = key;
heap_index[node] = insert_pos;
}
int min (struct heap * h, int i) {
int lc = 2 * i + 1;
int rc = 2 * i + 2;
if (lc < h->length && h->key[lc] < h->key[h->length])
i = lc;
if (rc < h->length && h->key[rc] < h->key[h->length])
i = rc;
return i;
}
int downheap ( struct heap * h, int * heap_index, int i) {
int j = min(h, i);
if ( j != i ) {
h->data[i] = h->data[j];
h->key[i] = h->key[j];
heap_index[h->data[i]] = i;
j = downheap(h,heap_index, j);
}
return j;
}
int pop (struct heap * h, int * heap_index) {
if ( h->length == 0 ) {
return INT_MIN;
}
int node = h->data[0];
h->length--;
int j = downheap(h,heap_index,0);
h->data[j] = h->data[h->length];
h->key[j] = h->key[h->length];
heap_index[h->data[h->length]] = j;
return node;
}
\ No newline at end of file
/*************************************
* Beispielprogramm zur Vorlesung
* Einfuehrung in die Programmierung I
* Andreas Paffenholz
* TU Darmstadt, Wintersemester 2020/21
* (c) 2020-
*
* Priority Queue als Heap, Header
**************************************/
#ifndef HEAP_H
#define HEAP_H
struct heap {
int *data;
int *key;
int length;
int size;
};
struct heap * init_heap (int, int);
void free_heap(struct heap *);
void print_heap(struct heap * h);
void push(struct heap *, int *, int, int);
int pop(struct heap *, int *);
void decrease_key (struct heap *, int *, int, int);
#endif
\ No newline at end of file
8
0 1 7
0 2 4
0 3 10
1 3 2
1 4 5
1 6 2
2 0 6
2 1 2
2 6 7
3 4 1
3 7 2
4 1 2
4 5 3
6 2 2
6 4 4
6 5 5
7 4 2
7 5 1
9
0 1 3
0 2 5
0 3 7
0 4 3
0 7 4
1 2 4
1 8 2
1 4 1
1 5 2
2 4 2
2 5 7
2 8 1
3 1 3
3 6 6
4 0 2
4 6 2
4 7 4
4 8 1
4 5 1
5 3 4
5 0 2
5 8 1
6 1 1
6 3 1
7 3 3
7 4 5
7 6 1
7 8 2
8 0 4
/*************************************
* Beispielprogramm zur Vorlesung
* Einfuehrung in die Programmierung I
* Andreas Paffenholz
* TU Darmstadt, Wintersemester 2020/21
* (c) 2020-
*
* Netzwerke
**************************************/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "network.h"
struct edge * init_edge(int head, int weight) {
struct edge * e = (struct edge *)malloc(sizeof(struct edge));
e->head = head;
e->weight = weight;
e->chosen = 1;
return e;
}
struct node * init_node() {
struct node * n = (struct node *)malloc(sizeof(struct node));
n->outgoing_edges = NULL;
n->n_outgoing_edges = 0;
n->edge_struct_size = 0;
n->visited = 0;
n->dist = INT_MAX;
n->pred = -1;
return n;
}
struct network * init_network(int n_nodes) {
struct network * g = (struct network *)malloc(sizeof(struct network));
g->nodes = (struct node **)malloc(n_nodes * sizeof(struct node *));
for ( int i = 0; i < n_nodes; ++i ) {
g->nodes[i] = init_node();
}
g->n_nodes = n_nodes;
int node_struct_size = n_nodes;
return g;
}
void free_edge(struct edge * e) {
free(e);
}
void free_node(struct node * n) {
for ( int i = 0; i < n->n_outgoing_edges; ++i ) {
free_edge(n->outgoing_edges[i]);
}
free(n->outgoing_edges);
free(n);
}
void free_network(struct network * g) {
for ( int i = 0; i < g->n_nodes; ++i ) {
free_node(g->nodes[i]);
}
free(g->nodes);
free(g);
}
int edge_exists(struct network * g, int tail, int head) {
struct node * n = g->nodes[tail];
for ( int i = 0; i < n->n_outgoing_edges; ++i ) {
if ( n->outgoing_edges[i]->head == head ) {
return 1;
}
}
return 0;
}
int add_edge(struct network * g, int tail, int head, int weight) {
if ( tail >= g->n_nodes || head >= g->n_nodes ) {
return -1;
}
struct node * n = g->nodes[tail];
if ( edge_exists(g,tail,head) ) {
return 1;
}
if (n->n_outgoing_edges >= n->edge_struct_size ) {
n->edge_struct_size = n->edge_struct_size ? n->edge_struct_size * 3 / 2 : 3;
n->outgoing_edges = realloc(n->outgoing_edges, n->edge_struct_size * sizeof (struct edge *));
}
n->outgoing_edges[n->n_outgoing_edges++] = init_edge(head,weight);
return 0;
}
struct network * read_network(char* filename) {
const char s[2] = " ";
FILE *infile;
infile = fopen (filename, "r");
if (infile == NULL) {
fprintf(stderr, "\nError opening file\n");
exit (1);
}
int n_nodes;
fscanf(infile, "%d", &n_nodes);
struct network * g = init_network(n_nodes);
int tail, head, weight;
while ( fscanf(infile, "%d %d %d", &tail, &head, &weight) != EOF ) {
add_edge(g,tail, head, weight);
}
fclose(infile);
return g;
}
/*************************************
* Beispielprogramm zur Vorlesung
* Einfuehrung in die Programmierung I
* Andreas Paffenholz
* TU Darmstadt, Wintersemester 2020/21
* (c) 2020-
*
* Netzwerke, Header
**************************************/
#ifndef NETWORK_H
#define NETWORK_H
struct edge {
int head;
int weight;
int chosen;
};
struct node {
struct edge ** outgoing_edges;
int edge_struct_size;
int n_outgoing_edges;
int visited;
int dist;
int pred;
};
struct network {
struct node ** nodes;
int node_struct_size;
int n_nodes;
};
struct network * init_network(int);
struct network * read_network(char*);
void free_network(struct network *);
#endif
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment