Commit 842f99c9 by Paffenholz, Andreas

parent a2da65b2
 ... ... @@ -12,27 +12,43 @@ void dijkstra (struct network * g, int start) { struct heap * h = init_heap(3, g->n_nodes); // initializize a heap as priotity queue // the heap keeps the node indices, not pointers to nodes struct heap * h = init_heap(3); // we need a secon list that tells us the current position of a node in the heap int * heap_index = (int *)malloc(g->n_nodes * sizeof(int)); for ( int i = 0; i < g->n_nodes; ++i) { heap_index[i] = 0; } // put root into heap // the root ha no predecessor, we mark this by -1 // elements not in the heap implicitly have distance 0 push(h, heap_index, start, 0); g->nodes[start]->pred=-1; g->nodes[start]->dist=0; g->nodes[start]->dist= 0; while (h->length) { // get the element with smallest distance int node_index = pop(h, heap_index); struct node * node = g->nodes[node_index]; node->visited = 1; node->visited = 1; // mark the current node as visited // now update distances to neighbors if necessary for (int j = 0; j < node->n_outgoing_edges; j++) { struct edge * e = node->outgoing_edges[j]; struct node * neighbor = g->nodes[e->head]; // we check if we have already seen the node, // then we do nothing, this node has already the correct distance // else we check if going to the node via the current one // creates a shorter path if (!neighbor->visited && node->dist + e->weight <= neighbor->dist) { neighbor->pred = node_index; neighbor->dist = node->dist + e->weight; // if its index in the heap is still zero, // then the node is not yet in the heap (still distance 0) // In that case we push with current distance // else we adjust the distance at the node if ( heap_index[e->head] == 0 ) push(h, heap_index, e->head, neighbor->dist); else ... ... @@ -40,10 +56,14 @@ void dijkstra (struct network * g, int start) { } } } // cleanup free(heap_index); free_heap(h); } // fill an array with the predecessors // once the algorithm of Dijkstra has run void predecessors(struct network * g, int * pred) { for ( int i = 0; i < g->n_nodes; ++i ) { pred[i] = g->nodes[i]->pred; ... ...
 ... ... @@ -17,7 +17,14 @@ #include "network.h" #include "heap.h" // compute distances and store those // and predecessors on the network // second argument is the start node void dijkstra (struct network *, int); // extract the predecessors from a network // on which Dijkstra's algorithm has run // second argument returns array with predecessors void predecessors(struct network *, int *); #endif \ No newline at end of file
 ... ... @@ -30,13 +30,17 @@ int main(int argc, char** argv) { int start = atoi(argv[2]); struct network * g = read_network(infile); // run algorithm dijkstra(g,start); // print distance for each node printf("The nodes have distance \n"); for ( int i = 0; i < g->n_nodes; ++i ) { printf("%d: %d\n", i, g->nodes[i]->dist); } // get predecessors int * pred = (int *)malloc(g->n_nodes * sizeof(int)); predecessors(g,pred); ... ... @@ -46,8 +50,9 @@ int main(int argc, char** argv) { printf("(%d, %d)\n", pred[i],i); } } free(pred); free(pred); free_network(g); return 0; } \ No newline at end of file
 ... ... @@ -14,7 +14,7 @@ #include "heap.h" struct heap * init_heap (int n, int index_size) { struct heap * init_heap (int n) { struct heap * h = (struct heap *)malloc(sizeof (struct heap)); h->data = (int *)malloc((n+1) * sizeof (int)); ... ... @@ -72,10 +72,14 @@ void decrease_key (struct heap * h, int * heap_index, int node, int key ) { void push (struct heap * h, int * heap_index, int node, int key ) { // adjust heap size if necessary if ( h->size <= h->length ) resize_heap(h); // find the new position before inserting // so upheap only needs to shift elems downwards int insert_pos = upheap(h, heap_index, h->length++, key); // move into place h->data[insert_pos] = node; h->key[insert_pos ] = key; heap_index[node] = insert_pos; ... ... @@ -107,9 +111,16 @@ int pop (struct heap * h, int * heap_index) { return INT_MIN; } //store the return int node = h->data[0]; h->length--; // the element we need to downheap // is in position h->length, we don't copy it into pos 0 // then downheap only needs to move elements upward // until we have found the new position int j = downheap(h,heap_index,0); // move the element into position // and fix head_index h->data[j] = h->data[h->length]; h->key[j] = h->key[h->length]; heap_index[h->data[h->length]] = j; ... ...
 ... ... @@ -18,14 +18,25 @@ struct heap { int size; }; struct heap * init_heap (int, int); // initialize a heap of given size struct heap * init_heap (int); void free_heap(struct heap *); void print_heap(struct heap * h); void push(struct heap *, int *, int, int); // push element // a array of element indices, // node node index // key distance at node void push(struct heap * h, int * a, int node, int key); // return root element int pop(struct heap *, int *); void decrease_key (struct heap *, int *, int, int); // adjust key at element // a array of element indices, // node node index // new_key adjusted distance at node void decrease_key (struct heap * h, int * a, int node, int new_key); #endif \ No newline at end of file
 ... ... @@ -21,18 +21,16 @@ struct edge * init_edge(int head, int 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->dist = INT_MAX; // no real distance should be that high 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 *)); ... ... @@ -64,6 +62,7 @@ void free_network(struct network * g) { free(g); } // checks if a given edge is in the network int edge_exists(struct network * g, int tail, int head) { struct node * n = g->nodes[tail]; ... ... @@ -75,25 +74,39 @@ int edge_exists(struct network * g, int tail, int head) { return 0; } // adds one edge to a network if not yet present int add_edge(struct network * g, int tail, int head, int weight) { // if nodes don't exist do nothing if ( tail >= g->n_nodes || head >= g->n_nodes ) { return -1; } struct node * n = g->nodes[tail]; // if edge exists to nothing if ( edge_exists(g,tail,head) ) { return 1; } // we may have to increase the storage size 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 *)); } // add the edge n->outgoing_edges[n->n_outgoing_edges++] = init_edge(head,weight); return 0; } /* for a network with n nodes we expect a file in the form --- n tail-1 head-1 weight-1 tail-2 head-2 weight-2 ... tail-n head-n weight-n --- */ struct network * read_network(char* filename) { const char s[2] = " "; FILE *infile; ... ...
 ... ... @@ -32,8 +32,12 @@ struct network { int n_nodes; }; struct network * init_network(int); // initialize a network of size n struct network * init_network(int n); // read network from file struct network * read_network(char*); void free_network(struct network *); #endif \ No newline at end of file
 ... ... @@ -19,11 +19,14 @@ #include "graham_scan.h" // check for left turn // by computing det of two vectors -> orientation int ccw(struct point* p1, struct point* p2, struct point* p3) { int turn = (p2->x - p1->x)*(p3->y - p1->y) - (p2->y - p1->y)*(p3->x - p1->x); return turn; } // among those with minimal y finde the one with minimal x int find_min(struct pointSet* pointset) { struct point* point = pointset->points; struct point* tmp = pointset->points; ... ... @@ -46,22 +49,32 @@ int find_min(struct pointSet* pointset) { void graham_scan(struct pointSet* pointset, int* verts, int* n_verts) { // some special cases // no points -> no convex hull if ( pointset->n_points == 0 ) { *n_verts = 0; verts[0] = 0; return; } // a single point is its own convex hull if ( pointset->n_points == 1 ) { *n_verts = 1; verts[0] = 0; return; } // now start graham scan // find start node int index = find_min(pointset); //place it at the beginning of the list swap(pointset, 0, index); // compute angles angles(pointset); // sort // we need distance to the start node as a tie breaker // if two points are collinear with the start node struct point* start = (struct point*)malloc(sizeof(struct point)); start->x = (pointset->points[0]).x; start->y = (pointset->points[0]).y; ... ... @@ -74,25 +87,32 @@ void graham_scan(struct pointSet* pointset, int* verts, int* n_verts) { free(start); // we build up a list of nodes on the convex hull // head gives the current last known node // of which we assume it is on the convex hull // just decrease head if we need to backtrack verts[0] = 0; verts[1] = 1; int head = 1; for(int i = 2; i <= pointset->n_points; i++){ // backtracking until we have left turn while(head >= 1 && ccw(pointset->points+verts[head-1], pointset->points+verts[head], pointset->points+(i % pointset->n_points)) <= 0 ) { pointset->points+(i % pointset->n_points)) <= 0 ) head--; } // add point, unless we have closed the polygon if ( i != pointset->n_points ) verts[head+1] = i; head++; } // if we have backtracked to the start node, but there is another node, // then put this as the next node if ( head == 1 ) { if ( pointset->points->x != (pointset->points+verts[1])->x || pointset->points->y != (pointset->points+verts[1])->y ) head++; ... ...
 ... ... @@ -13,6 +13,11 @@ #include "point_set.h" // do a graham scan on the set of points // given in the point set // returns indices of points on the convex hull // and total number of vertives // in the last two arguments void graham_scan(struct pointSet*, int*, int*); #endif \ No newline at end of file
 ... ... @@ -47,12 +47,18 @@ int compare(const void* a, const void* b, void* c) { return (c1 > c2) - (c2 > c1); } // swap two points in the list void swap(struct pointSet* pointset, int i1, int i2) { struct point tmp = pointset->points[i1]; pointset->points[i1] = pointset->points[i2]; pointset->points[i2] = tmp; } // compute a representative of the angle for the vector from p2 tp p1 with the x-axis // we use the negative of the squared cosine, // where we preserve the sign of cos before we square // this is a rational number, which we store as (num,denom) // special case: start node, make it smallest, so it comes first void angle(struct point* p1, struct point* p2, int* num, int* denom) { int dot = p2->x-p1->x; *num = (dot<0?-1:1)*dot*dot; ... ... @@ -63,6 +69,8 @@ void angle(struct point* p1, struct point* p2, int* num, int* denom) { } } // return list of all angles of // a ray from the start node to another node with the x-axis void angles(struct pointSet* pointset) { int num, denom; (pointset->points[0]).angle_num = -1; ... ... @@ -78,6 +86,9 @@ void angles(struct pointSet* pointset) { } } // read a list of points in the plane // with integral coeffs // each line gives coords (x,y) for one point struct pointSet* read_input(char* filename) { FILE *infile; infile = fopen (filename, "r"); ... ... @@ -138,6 +149,8 @@ void print_points(struct pointSet* pointset, int show_angle ) { printf("---------------------------------\n"); } // write result to a file // gives a list of points on the convex hull void store_verts(struct pointSet* pointset, int* verts, int n_verts, char* filename) { FILE* file = fopen(filename, "w"); fprintf(file, "%d\n", n_verts); ... ...
 ... ... @@ -29,10 +29,22 @@ int compare(void*, const void*, const void*); int compare(const void*, const void*, void*); #endif // read from file struct pointSet* read_input(char*); void store_verts(struct pointSet*, int*, int, char*); // store the vertices of the convex hull in a file // p original point set // v array of indices of the vertices among p // nv size of nv // f filename void store_verts(struct pointSet* p, int* v, int nv, char* f); // swap two points in a point set given by indices void swap(struct pointSet* , int, int); // compute the angles of all points in a pointset // of the ray from the first point to all other points // to the x-axis void angles(struct pointSet* ); void print_points(struct pointSet*,int); ... ...
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!