added tests as prepared by oliver
This commit is contained in:
369
test/ref/dijkstra.c
Normal file
369
test/ref/dijkstra.c
Normal file
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
!!DESCRIPTION!! Dijkstras Algorithm
|
||||
!!ORIGIN!! testsuite
|
||||
!!LICENCE!! Public Domain
|
||||
!!AUTHOR!! Groepaz/Hitmen
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void*)0)
|
||||
#endif
|
||||
|
||||
#define DIJKSTRA_INFINITY (0xffff)
|
||||
|
||||
#define DIJKSTRA_FLAG_UNVISITED (0x0)
|
||||
/*
|
||||
#define DIJKSTRA_FLAG_OPEN (0x1)
|
||||
*/
|
||||
#define DIJKSTRA_FLAG_CLOSED (0x2)
|
||||
|
||||
typedef struct _DIJKSTRA_EDGE {
|
||||
struct _DIJKSTRA_NODE *NEXTNODE;
|
||||
unsigned short DISTANCE;
|
||||
} DIJKSTRA_EDGE;
|
||||
|
||||
typedef struct _DIJKSTRA_NODE {
|
||||
DIJKSTRA_EDGE *EDGES;
|
||||
unsigned char TAG;
|
||||
unsigned char FLAG;
|
||||
unsigned short MINDIST;
|
||||
struct _DIJKSTRA_NODE *PREVIOUS;
|
||||
} DIJKSTRA_NODE;
|
||||
|
||||
/* init with graph, startnode, working-array */
|
||||
void Dijkstra_Init(const DIJKSTRA_NODE *graph,DIJKSTRA_NODE *start,DIJKSTRA_NODE *nodes);
|
||||
|
||||
/* call main algo with working-array */
|
||||
void Dijkstra_Search(DIJKSTRA_NODE *nodes);
|
||||
|
||||
/* print path, call with working-array, endnode */
|
||||
void Dijkstra_Path(DIJKSTRA_NODE *nodes,DIJKSTRA_NODE *end);
|
||||
|
||||
/* print table, call with working-array, current node */
|
||||
void Dijkstra_Table(DIJKSTRA_NODE *nodes,DIJKSTRA_NODE *current);
|
||||
|
||||
/* internally used routines */
|
||||
|
||||
unsigned short Dijkstra_Distance(DIJKSTRA_NODE *currnode,DIJKSTRA_NODE *nextnode);
|
||||
void Dijkstra_Relax(DIJKSTRA_NODE *currnode,DIJKSTRA_NODE *nextnode);
|
||||
DIJKSTRA_NODE *Dijkstra_NextCheapest(DIJKSTRA_NODE *graph);
|
||||
unsigned short Dijkstra_CountUnvisited(DIJKSTRA_NODE *graph);
|
||||
|
||||
/* define to get printed info as the algorithm proceeds */
|
||||
#define DIJKSTRA_PRINTDEBUG
|
||||
|
||||
/* the working array */
|
||||
DIJKSTRA_NODE mynodes[0x10];
|
||||
|
||||
/* test-network data (mypoints and myedges) */
|
||||
|
||||
const DIJKSTRA_EDGE myedges_A[]={
|
||||
{&mynodes[1],1},
|
||||
{NULL}
|
||||
};
|
||||
const DIJKSTRA_EDGE myedges_B[]={
|
||||
{&mynodes[0],1},
|
||||
{&mynodes[2],2},
|
||||
{&mynodes[3],1},
|
||||
{NULL}
|
||||
};
|
||||
const DIJKSTRA_EDGE myedges_C[]={
|
||||
{&mynodes[1],2},
|
||||
{&mynodes[5],1},
|
||||
{NULL}
|
||||
};
|
||||
const DIJKSTRA_EDGE myedges_D[]={
|
||||
{&mynodes[1],1},
|
||||
{&mynodes[4],1},
|
||||
{NULL}
|
||||
};
|
||||
const DIJKSTRA_EDGE myedges_E[]={
|
||||
{&mynodes[6],1},
|
||||
{NULL}
|
||||
};
|
||||
const DIJKSTRA_EDGE myedges_F[]={
|
||||
{&mynodes[7],1},
|
||||
{NULL}
|
||||
};
|
||||
const DIJKSTRA_EDGE myedges_G[]={
|
||||
{&mynodes[8],1},
|
||||
{&mynodes[7],4},
|
||||
{NULL}
|
||||
};
|
||||
const DIJKSTRA_EDGE myedges_H[]={
|
||||
{&mynodes[9],1},
|
||||
{&mynodes[6],4},
|
||||
{NULL}
|
||||
};
|
||||
const DIJKSTRA_EDGE myedges_I[]={
|
||||
{&mynodes[10],5},
|
||||
{NULL}
|
||||
};
|
||||
const DIJKSTRA_EDGE myedges_J[]={
|
||||
{&mynodes[10],1},
|
||||
{NULL}
|
||||
};
|
||||
const DIJKSTRA_EDGE myedges_K[]={
|
||||
{&mynodes[11],1},
|
||||
{NULL}
|
||||
};
|
||||
const DIJKSTRA_EDGE myedges_L[]={
|
||||
{&mynodes[10],1},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
const DIJKSTRA_NODE mypoints[]={
|
||||
{(DIJKSTRA_EDGE *)&myedges_A[0],'A'},
|
||||
{(DIJKSTRA_EDGE *)&myedges_B[0],'B'},
|
||||
{(DIJKSTRA_EDGE *)&myedges_C[0],'C'},
|
||||
{(DIJKSTRA_EDGE *)&myedges_D[0],'D'},
|
||||
{(DIJKSTRA_EDGE *)&myedges_E[0],'E'},
|
||||
{(DIJKSTRA_EDGE *)&myedges_F[0],'F'},
|
||||
{(DIJKSTRA_EDGE *)&myedges_G[0],'G'},
|
||||
{(DIJKSTRA_EDGE *)&myedges_H[0],'H'},
|
||||
{(DIJKSTRA_EDGE *)&myedges_I[0],'I'},
|
||||
{(DIJKSTRA_EDGE *)&myedges_J[0],'J'},
|
||||
{(DIJKSTRA_EDGE *)&myedges_K[0],'K'},
|
||||
{(DIJKSTRA_EDGE *)&myedges_L[0],'L'},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
/*
|
||||
* initialize working-array
|
||||
*/
|
||||
|
||||
void Dijkstra_Init(const DIJKSTRA_NODE *graph,DIJKSTRA_NODE *start,DIJKSTRA_NODE *nodes) {
|
||||
while(graph->EDGES!=NULL) {
|
||||
nodes->EDGES=graph->EDGES;
|
||||
nodes->TAG=graph->TAG;
|
||||
nodes->FLAG=DIJKSTRA_FLAG_UNVISITED;
|
||||
nodes->MINDIST=DIJKSTRA_INFINITY;
|
||||
nodes->PREVIOUS=NULL;
|
||||
|
||||
graph++;nodes++;
|
||||
|
||||
}
|
||||
/*
|
||||
start->FLAG=DIJKSTRA_FLAG_OPEN;
|
||||
start->PREVIOUS=NULL;
|
||||
*/
|
||||
start->MINDIST=0;
|
||||
}
|
||||
|
||||
/*
|
||||
* compute the distance between two Nodes in the Graph
|
||||
*/
|
||||
|
||||
unsigned short Dijkstra_Distance(DIJKSTRA_NODE *currnode,DIJKSTRA_NODE *nextnode){
|
||||
DIJKSTRA_EDGE *edge;
|
||||
|
||||
edge=currnode->EDGES;
|
||||
|
||||
while(edge!=NULL) {
|
||||
if(edge->NEXTNODE == nextnode){
|
||||
return(edge->DISTANCE);
|
||||
}
|
||||
|
||||
edge++;
|
||||
|
||||
}
|
||||
|
||||
return(DIJKSTRA_INFINITY);
|
||||
}
|
||||
|
||||
/*
|
||||
* 'relax' one node against another
|
||||
*/
|
||||
|
||||
void Dijkstra_Relax(DIJKSTRA_NODE *currnode,DIJKSTRA_NODE *nextnode){
|
||||
unsigned short newdist;
|
||||
|
||||
#ifdef DIJKSTRA_PRINTDEBUG
|
||||
printf("relax >%c< to >%c<\n",currnode->TAG,nextnode->TAG);
|
||||
#endif
|
||||
|
||||
newdist=currnode->MINDIST+Dijkstra_Distance(currnode,nextnode);
|
||||
|
||||
if((nextnode->MINDIST)>(newdist)){
|
||||
nextnode->MINDIST=newdist;
|
||||
nextnode->PREVIOUS=currnode;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* find the yet unprocessed Node with the currently
|
||||
* smallest estimated MINDIST
|
||||
*/
|
||||
|
||||
DIJKSTRA_NODE *Dijkstra_NextCheapest(DIJKSTRA_NODE *graph){
|
||||
unsigned short mindist;
|
||||
DIJKSTRA_NODE *node;
|
||||
|
||||
node=NULL;
|
||||
mindist=DIJKSTRA_INFINITY;
|
||||
|
||||
while(graph->EDGES!=NULL) {
|
||||
if(graph->FLAG!=DIJKSTRA_FLAG_CLOSED){
|
||||
if(!(mindist<graph->MINDIST)){
|
||||
mindist=graph->MINDIST;
|
||||
node=graph;
|
||||
}
|
||||
}
|
||||
|
||||
graph++;
|
||||
|
||||
}
|
||||
|
||||
#ifdef DIJKSTRA_PRINTDEBUG
|
||||
if(node!=NULL) printf("next cheapest Node: >%c<\n",node->TAG);
|
||||
#endif
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
||||
/*
|
||||
* count number of Nodes that are left for processing
|
||||
*/
|
||||
|
||||
unsigned short Dijkstra_CountUnvisited(DIJKSTRA_NODE *graph){
|
||||
unsigned short num;
|
||||
|
||||
num=0;
|
||||
|
||||
while(graph->EDGES!=NULL) {
|
||||
if(graph->FLAG!=DIJKSTRA_FLAG_CLOSED){
|
||||
num++;
|
||||
}
|
||||
|
||||
graph++;
|
||||
|
||||
}
|
||||
|
||||
return(num);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dijkstra-Algorithmus main processing
|
||||
*/
|
||||
|
||||
void Dijkstra_Search(DIJKSTRA_NODE *graph){
|
||||
DIJKSTRA_NODE *currnode,*nextnode;
|
||||
DIJKSTRA_EDGE *edge;
|
||||
|
||||
currnode=graph;
|
||||
|
||||
while(Dijkstra_CountUnvisited(graph)>0){
|
||||
edge=currnode->EDGES;
|
||||
while(edge->NEXTNODE!=NULL){
|
||||
nextnode=edge->NEXTNODE;
|
||||
if(nextnode->FLAG!=DIJKSTRA_FLAG_CLOSED){
|
||||
/*
|
||||
nextnode->FLAG=DIJKSTRA_FLAG_OPEN;
|
||||
*/
|
||||
Dijkstra_Relax(currnode,nextnode);
|
||||
#ifdef DIJKSTRA_PRINTDEBUG
|
||||
Dijkstra_Table(graph,currnode);
|
||||
#endif
|
||||
}
|
||||
edge++;
|
||||
}
|
||||
currnode=Dijkstra_NextCheapest(graph);
|
||||
currnode->FLAG=DIJKSTRA_FLAG_CLOSED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* print the Path from start Node to one other Node
|
||||
*/
|
||||
|
||||
void Dijkstra_Path(DIJKSTRA_NODE *graph,DIJKSTRA_NODE *end){
|
||||
DIJKSTRA_NODE *currnode,*nextnode;
|
||||
|
||||
printf("Path from >%c< to >%c< : ",end->TAG,graph->TAG);
|
||||
|
||||
currnode=end;
|
||||
|
||||
while(currnode->PREVIOUS!=NULL){
|
||||
printf(">%c< ",currnode->TAG);
|
||||
currnode=currnode->PREVIOUS;
|
||||
}
|
||||
|
||||
printf(">%c<\n",currnode->TAG);
|
||||
}
|
||||
|
||||
/*
|
||||
* print working-array as a table
|
||||
*/
|
||||
|
||||
void Dijkstra_Table(DIJKSTRA_NODE *graph,DIJKSTRA_NODE *current){
|
||||
DIJKSTRA_NODE *g;
|
||||
|
||||
printf("----------------------\n");
|
||||
|
||||
printf("Node |");
|
||||
g=graph;while(g->EDGES!=NULL) {
|
||||
printf("-->%c<-|",g->TAG);
|
||||
g++;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("MinDist |");
|
||||
g=graph;while(g->EDGES!=NULL) {
|
||||
printf(" %5u|",g->MINDIST);
|
||||
g++;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("Flag |");
|
||||
g=graph;while(g->EDGES!=NULL) {
|
||||
switch(g->FLAG){
|
||||
/*
|
||||
case DIJKSTRA_FLAG_OPEN:
|
||||
printf("opened|");
|
||||
break;
|
||||
*/
|
||||
case DIJKSTRA_FLAG_CLOSED:
|
||||
printf("closed|");
|
||||
break;
|
||||
default:
|
||||
if(g->MINDIST!=DIJKSTRA_INFINITY){
|
||||
printf("opened|");
|
||||
} else {
|
||||
printf("------|");
|
||||
}
|
||||
break;
|
||||
}
|
||||
g++;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("Previous|");
|
||||
g=graph;while(g->EDGES!=NULL) {
|
||||
if(g->PREVIOUS==NULL)
|
||||
printf("------|");
|
||||
else
|
||||
printf(" (%c) |",g->PREVIOUS->TAG);
|
||||
g++;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("----------------------\n");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* init with graph, startnode, working-array */
|
||||
Dijkstra_Init(&mypoints[0],&mynodes[0],&mynodes[0]);
|
||||
/* call main algo with working-array */
|
||||
Dijkstra_Search(&mynodes[0]);
|
||||
/* print table, call with working-array, endnode */
|
||||
Dijkstra_Table(&mynodes[0],&mynodes[11]);
|
||||
/* print path, call with working-array, endnode */
|
||||
Dijkstra_Path(&mynodes[0],&mynodes[11]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user