I have been making an algorithm that builds a Minimum Spanning Tree where I insert the number of cities (vertexes), airports (edges connecting to a "sky" vertex - vertex 0) and the number of roads (edges connected to other cities).
I then insert the city the airport (source vertex) is built and the cost (edge cost).
After this, I insert the cities connected by roads (source and destiny vertexes) and the cost (edge cost).
The outputs are the MST cost, the number of airports and number of roads.
I already have these mechanisms working but they are a bit buggy. I can't seem to fix these issues.
Also, I was wondering if I can make a function that detects if the undirected graph in the MST is connected (all vertexes are connected). If the function detects that the MST is not connected, the program should output "Insuficient information.".
Full code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// A structure to represent a weighted edge in graph.
struct Edge {
int src, dest, weight;
};
// A structure to represent a connected, undirected and weighted graph.
struct Graph {
// V -> Vertex Number (Number of cities), E -> Number of edges (Number of roads + airport connections).
int V;
int E;
// The graph is represented as an array of edges.
// Since the graph is undirected, the edge
// from src to dest is also edge from dest
// to src. Both are counted as 1 edge here.
struct Edge* edge;
};
// Creates a graph with V vertexes and E edges.
struct Graph* createGraph(int V, int E)
{
struct Graph* graph = malloc(sizeof *graph);
graph->V = V;
graph->E = E;
graph->edge = (struct Edge*)malloc(E * sizeof(struct Edge));
return graph;
};
// A structure to represent a subset for union-find.
struct subset {
int parent;
int rank;
};
// A utility function to find set of an element (uses path compression technique).
int find(struct subset subsets[], int i)
{
// Find root and make root as parent of i (uses path compression technique).
if (subsets[i].parent != i)
subsets[i].parent
= find(subsets, subsets[i].parent);
return subsets[i].parent;
}
// A function that does union of two sets of x and y (uses union by rank).
void Union(struct subset subsets[], int x, int y)
{
int xroot = find(subsets, x);
int yroot = find(subsets, y);
// Attach smaller rank tree under root of high rank tree (Union by Rank).
if (subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if (subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
// If ranks are same, then make one as root and increment its rank by one.
else
{
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
// Compare two edges according to their weights.
// Used in qsort() for sorting an array of edges.
int myComp(const void* a, const void* b)
{
struct Edge* a1 = (struct Edge*)a;
struct Edge* b1 = (struct Edge*)b;
if (a1->weight > b1->weight) {
return a1->weight > b1->weight;
}
if (a1->weight < b1->weight) {
return a1->weight < b1->weight;
}
if (a1->weight == b1->weight) {
return a1->weight == b1->weight;
}
}
// The main function to construct MST using Kruskal's algorithm.
void KruskalMST(struct Graph* graph)
{
int V = graph->V;
struct Edge
result[V]; // Saves the resulting MST.
int e = 0; // An index variable, used for result[].
int i = 0; // An index variable, used for sorted edges.
// Step 1: Sort all the edges in non-decreasing order of their weight.
// If we are not allowed to change the given graph, we can create a copy of array of edges.
qsort(graph->edge, graph->E, sizeof(graph->edge[0]),
myComp);
// Allocate memory for creating V ssubsets.
struct subset* subsets
= (struct subset*)malloc(V * sizeof(struct subset));
// Create V subsets with single elements.
for (int v = 0; v < V; ++v) {
subsets[v].parent = v;
subsets[v].rank = 0;
}
// Number of edges to be taken is equal to V-1.
while (e < V - 1 && i < graph->E) {
// Step 2: Pick the smallest edge.
// And increment the index for next iteration.
struct Edge next_edge = graph->edge[i++];
int x = find(subsets, next_edge.src);
int y = find(subsets, next_edge.dest);
// If including this edge does't cause cycle,
// include it in result and increment the index
// of result for next edge.
if (x != y) {
result[e++] = next_edge;
Union(subsets, x, y);
}
// Else discard the next_edge.
}
int minimumCost = 0;
int nRoads = 0;
int nAirports = 0;
for (i = 0; i < e; ++i)
{
if (result[i].dest == 0) {
nAirports++;
} else {
nRoads++;
}
minimumCost += result[i].weight;
}
printf("Minimum Spanning Tree with minimal cost: %d\n",minimumCost);
printf("Number of airports: %d\n",nAirports);
printf("Number of roads: %d",nRoads);
return;
}
int main()
{
int v = 0; // Number of vertexes(cities) in the graph (includes the "sky" vertex).
int a = 0; // Number of airports.
int edges = 0; // Number of roads.
int e = 0; // Number Total number of edges in the graph.
int city = 0;
int airport = 0;
int city1 = 0;
int city2 = 0;
int cost = 0;
printf("Input the number of cities: \n");
scanf("%d", &v);
printf("Input the number of airports: \n");
scanf("%d", &a);
printf("Input the number of roads: \n");
scanf("%d", &e);
edges = a + e;
if (a > 0) {
v = v + 1;
}
struct Graph* graph = createGraph(v, edges);
for (int i = 0; i < a; i++) {
printf("Input the city and the building cost of the airport: \n");
scanf("%d %d", &city, &airport);
graph->edge[i].src = city;
graph->edge[i].dest = 0; // "sky" vertex.
graph->edge[i].weight = airport;
}
for (int j = a; j < edges; j++) {
printf("Input the cities and the cost of the road: \n");
scanf("%d %d %d", &city1, &city2, &cost);
if (a == 0) {
graph->edge[j].src = city1 - 1;
graph->edge[j].dest = city2 - 1;
graph->edge[j].weight = cost;
} else {
graph->edge[j].src = city1;
graph->edge[j].dest = city2;
graph->edge[j].weight = cost;
}
}
KruskalMST(graph);
return 0;
}
Example of a bug - 0 airports declared but still counts an airport:
Input the number of cities:
4
Input the number of airports:
0
Input the number of roads:
4
Input the cities and the cost of the road:
1 2 1
Input the cities and the cost of the road:
2 3 2
Input the cities and the cost of the road:
3 4 1
Input the cities and the cost of the road:
4 1 1
Minimum Spanning Tree with minimal cost: 3
Number of airports: 1
Number of roads: 2
The expected number of airports should be 0.
Related
I am having trouble with the logic of combining these two stipulations in my assignment. How do I change the below binary search function to intake the compareTo the coordinate structures. I wrote it wrong the first time because I used the original string locations. I also dont understand how the compareTo function is suppose to keep track of the length away from the target. Which is confusing to me because the way it reads below for the compareTo function says the opposite to me and asking me to compare individual x and y coordinates. how am I suppose to do that if i am just using the pointers? Am i just passing coordinates *ptrPt1 into the binary search? Number 3 is the most confusing mess of words.
Context for the function relationship:
You must write a function compareTo which takes in two pointers, ptrPt1 and ptrPt2, to
coordinate structs and returns a negative integer if the point pointed to by ptrPt1 is closer to you
than the point pointed to by ptrPt2, 0 if the two locations pointed to by both are identical locations,
and a positive integer if the point pointed to by ptrPt1 is farther from you than the point pointed to
by ptrPt2. Exceptions to this will be when the two pointers are pointing to points that are the same
distance from you, but are distinct points. In these cases, if ptrPt1's x coordinate is lower than
ptrPt2's x coordinate, a negative integer must be returned. Alternatively, if ptrPt1's x coordinate is
greater than ptrPt2's x coordinate a positive integer must be returned. Finally, if the x coordinate
of both points is the same, if ptrPt1's y coordinate is lower than ptrPt2's y coordinate, a negative
integer must be returned. If ptrPt1's y coordinate is greater than ptrPt2's y coordinate, a positive
integer must be returned.
Since your location must be used for sorting, please make the variable that stores your x and y
coordinates global. Your program should have no other global variables.
A Binary Search function must be used when answering queries.
int binarysearch(int searchval, int* array, int length) {
int low = 0, high = length-1;
// Search while there is a valid search space.
while (low <= high) {
int mid = (low+high)/2;
// Value is too small.
if (searchval < array[mid])
high = mid-1;
// too big.
else if (searchval > array[mid])
low = mid+1;
// found it!
else
return 1;
}
// Never found it.
return 0;
}
int
compareTo(coordinates *ptrPt1, coordinates *ptrPt2) {
if (ptrPt1 > ptrPt2)
return -1;
if(ptrPt1 == ptrPt2)
return 0;
if(ptrPt1 < ptrPt2)
return 1;
}
Your compareTo needs to be refactored.
Comparing the addresses of the structs [vs. the X/Y coordinates within them] is incorrect.
For compareTo, it must first compute the distance from an arbitrary reference point (e.g.) self for each of the two points passed as arguments. Per the problem definition, self can [and should] be a [the only] global.
It gets the distance to self for each of the two [argument] points. It chooses the closer of these two points [if they are different].
If the two points are the same distance from the self point, it first chooses the one with the lower X coordinate value. If the X coordinates are the same for the two points, it chooses the one that has the lower of the two Y values.
Thus, it's a three step process.
Your binarysearch needs to be refactored. Upon mismatch/failure, it returns 0. But, zero is a valid index/value for a match. So, it needs to return -1 on failure.
There are some issues with the problem definition.
Issue (1):
It's not clear [to me] what "rank" is supposed to be. The only thing that makes sense is that "rank" is the index into the list that is sorted by compareTo.
Issue (2):
It's not clear what "distance" means. It could be (e.g.):
sqrt((p1->x - p2->x)**2 + (p1->y - p2->y)**2)
But, that uses floating point, and it may be overkill for this problem.
Another "distance" is the manhattan distance which is just the sum of the absolute differences of the X and Y values of the two coordinates:
abs(p1->x - p2->x) + abs(p1->y - p2->y)
Issue (3):
I think that two sorted lists are required.
One sorted by compareTo. Another sorted just by X/Y coordinates.
This is because it is required to use a binary search when matching a search coordinate. Because the search coordinate does not know the rank, it can't use the compareTo list and must use the X/Y list.
There are two possible approaches.
This can be achieved by using two lists that are either pointers or indices into the person list. The binarysearch should be modified to accept an array of indices/pointers.
Or, it can be achieved by sorting the person list by compareTo, recording the rank in the coordinate struct and then resorting the list by X/Y coordinates. The binarysearch should be modified to accept an array of coordinates.
I've chosen to use the latter approach.
And, I've added some test code to generate a randomized input file, if desired.
I've just implemented a simple insertion sort [algorithm is a cut-n-paste from the wikipedia entry for insertion sort]. So, you'll still have to code up the combined merge/insertion sort logic.
Spoiler Alert: Below is the complete/refactored code:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <time.h>
typedef struct {
int x;
int y;
int rank;
} coord_t;
// maximum coordinate
#ifndef COORDMAX
#define COORDMAX 10000
#endif
// max # of [infected] people
#ifndef PERSONMAX
#define PERSONMAX 106
#endif
#define SEARCHMAX (2 * (PERSONMAX - 1)) // max # of search coordinates
#define THRESHMAX 30 // maximum threshold
coord_t self; // coordinates of tracer
typedef int (*cmpfnc_p)(const coord_t *,const coord_t *);
int opt_d; // 1=debug
int opt_f; // distance mode (0=manhattan, 1=sqrt)
unsigned int opt_R; // random fill
void gentest(FILE *fi);
// disti -- get distance from given coordinate to self (manhattan distance)
int
disti(const coord_t *pt)
{
int dif;
int tot = 0;
dif = pt->x - self.x;
if (dif < 0)
dif = -dif;
tot += dif;
dif = pt->y - self.y;
if (dif < 0)
dif = -dif;
tot += dif;
return tot;
}
// distf -- get distance from given coordinate to self (floating pt distance)
int
distf(const coord_t *pt)
{
double dif;
double tot = 0;
int rtn;
dif = pt->x - self.x;
dif *= dif;
tot += dif;
dif = pt->y - self.y;
dif *= dif;
tot += dif;
tot = sqrt(tot);
// scale result
// FIXME -- this is untested and may not be necessary
tot *= INT_MAX;
tot /= COORDMAX;
rtn = round(tot);
return rtn;
}
// dist -- get distance from given coordinate to self
int
dist(const coord_t *pt)
{
int tot;
if (opt_f)
tot = distf(pt);
else
tot = disti(pt);
return tot;
}
// compareAbs -- compare two coordinates for lowest X/Y values
int
compareAbs(const coord_t *p1,const coord_t *p2)
{
int cmp;
do {
// use lower X coordinate
cmp = p1->x - p2->x;
if (cmp)
break;
// use lower Y coordinate
cmp = p1->y - p2->y;
if (cmp)
break;
} while (0);
return cmp;
}
// compareTo -- compare two coordinates for distance from self and then position
int
compareTo(const coord_t *p1,const coord_t *p2)
{
int cmp;
do {
// compare distance to self
cmp = dist(p1) - dist(p2);
if (cmp)
break;
// compare against absolute coordinates
cmp = compareAbs(p1,p2);
} while (0);
return cmp;
}
// sortswap -- swap array elements
void
sortswap(coord_t *p1,coord_t *p2)
{
coord_t tmp;
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
// sortinsert -- insertion sort
void
sortinsert(coord_t *list,int count,cmpfnc_p cmp)
{
for (int i = 1; i < count; ++i) {
for (int j = i; j > 0; --j) {
if (cmp(&list[j - 1],&list[j]) <= 0)
break;
sortswap(&list[j - 1],&list[j]);
}
}
}
// sortany -- outer sort routine
void
sortany(coord_t *list,int count,int threshold,cmpfnc_p cmp)
{
// TODO: do mergesort
if (count < threshold) {
}
// finish with insertion sort
sortinsert(list,count,cmp);
}
// binarysearch -- perform binary search on coordinate list
int
binarysearch(const coord_t *search,const coord_t *array,int length,
cmpfnc_p cmpfnc)
{
int low = 0;
int high = length - 1;
int match = -1;
// Search while there is a valid search space.
while (low <= high) {
int mid = (low + high) / 2;
int cmp = cmpfnc(search,&array[mid]);
// found it
if (cmp == 0) {
match = mid;
break;
}
// Value is too small.
if (cmp < 0)
high = mid - 1;
// too big.
else
low = mid + 1;
}
return match;
}
// main -- main program
int
main(int argc,char **argv)
{
const char *file = NULL;
char *cp;
FILE *fi;
int person_count;
int search_count;
int threshold;
coord_t *pt;
coord_t *person_list;
coord_t *search_list;
--argc;
++argv;
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
case 'd':
opt_d = ! opt_d;
break;
case 'f':
opt_f = ! opt_f;
break;
case 'R':
cp += 2;
opt_R = (*cp != 0) ? atoi(cp) : time(NULL);
printf("R=%u\n",opt_R);
srand(opt_R);
break;
}
}
// get/open input file
do {
fi = stdin;
if (argc <= 0) {
if (opt_R)
fi = stdout;
else
fi = stdin;
break;
}
file = *argv;
fi = fopen(file,opt_R ? "w" : "r");
if (fi == NULL) {
perror(file);
exit(1);
}
} while (0);
// generate test data
if (opt_R) {
gentest(fi);
fclose(fi);
exit(0);
}
fscanf(fi,"%d %d %d %d %d",
&self.x,&self.y,&person_count,&search_count,&threshold);
person_list = calloc(person_count,sizeof(*person_list));
if (person_list == NULL) {
perror("person_list");
exit(1);
}
search_list = calloc(search_count,sizeof(*search_list));
if (search_list == NULL) {
perror("search_list");
exit(1);
}
// read in coordinates of all people
for (int idx = 0; idx < person_count; ++idx) {
pt = &person_list[idx];
fscanf(fi,"%d %d",&pt->x,&pt->y);
}
// read in all search coordinates
for (int idx = 0; idx < search_count; ++idx) {
pt = &search_list[idx];
fscanf(fi,"%d %d",&pt->x,&pt->y);
}
// get the ranking
sortany(person_list,person_count,threshold,compareTo);
// remember the ranking and print the ranked list
for (int idx = 0; idx < person_count; ++idx) {
pt = &person_list[idx];
pt->rank = idx;
if (opt_d)
printf("%d %d dist=%d rank=%d\n",pt->x,pt->y,dist(pt),idx);
else
printf("%d %d\n",pt->x,pt->y);
}
// reorder list for search points
sortany(person_list,person_count,threshold,compareAbs);
// perform all queries
for (int idx = 0; idx < search_count; ++idx) {
pt = &search_list[idx];
int match = binarysearch(pt,person_list,person_count,compareAbs);
if (match < 0) {
printf("%d %d not found\n",pt->x,pt->y);
continue;
}
pt = &person_list[match];
printf("%d %d found at rank %d\n",pt->x,pt->y,pt->rank);
}
if (file != NULL)
fclose(fi);
free(person_list);
free(search_list);
return 0;
}
// gencoord -- generate a random coordinate
void
gencoord(coord_t *pt)
{
int val;
int neg;
for (int mode = 0; mode <= 1; ++mode) {
val = rand();
neg = (val & 1);
val >>= 1;
val %= (COORDMAX + 1);
if (neg)
val = -val;
if (mode == 0)
pt->x = val;
else
pt->y = val;
}
}
// genrand -- genrate a random number in the inclusive range
int
genrand(int lo,int hi)
{
int val;
val = rand();
val %= (hi + 1);
if (val < lo)
val = lo;
return val;
}
// gensame -- decide if coordinate already in use
int
gensame(coord_t *pt,coord_t *list,int length)
{
int match;
do {
// coordinate may _not_ be the starting/self point
match = (compareAbs(pt,&self) == 0);
if (match)
break;
// coordinate may not match any previous point in the list
for (int idx = 0; idx < length; ++idx) {
match = (compareAbs(pt,&list[idx]) == 0);
if (match)
break;
}
} while (0);
return match;
}
// gentest -- generate a random test file
void
gentest(FILE *fi)
{
int val;
int threshold;
int person_count;
int search_count;
int same;
coord_t *person_list;
coord_t *pt;
coord_t tmp;
gencoord(&self);
person_count = genrand(2,PERSONMAX);
search_count = genrand(1,SEARCHMAX);
threshold = genrand(1,THRESHMAX);
fprintf(fi,"%d %d %d %d %d\n",
self.x,self.y,person_count,search_count,threshold);
person_list = calloc(person_count,sizeof(*person_list));
if (person_list == NULL) {
perror("person_list");
exit(1);
}
// generate coordinates of all people
fprintf(fi,"\n");
for (int idx = 0; idx < person_count; ++idx) {
pt = &person_list[idx];
pt->rank = 0;
// ensure [proposed] coordinate is unique
same = 1;
while (same) {
gencoord(pt);
same = gensame(pt,person_list,idx);
}
fprintf(fi,"%d %d\n",pt->x,pt->y);
}
// generate search coordinates
fprintf(fi,"\n");
for (int idx = 0; idx < search_count; ++idx) {
pt = &tmp;
val = rand();
val %= 100;
// generate a random point that is _not_ a person or self (10% of the
// time)
if (val < 10) {
same = 1;
while (same) {
gencoord(pt);
same = gensame(pt,person_list,person_count);
}
}
// randomly select an infected person
else {
val = genrand(0,person_count - 1);
pt = &person_list[val];
}
fprintf(fi,"%d %d\n",pt->x,pt->y);
}
free(person_list);
}
I was working on Kruskal algorithm that will read input and based on this information it will find the shortest path between every two nodes.
Let me explain:
There are numbers on the input, for example:
7 6 1 5
1 7 20
7 2 5
2 3 9
4 2 4
5 2 7
6 5 3
On the first line there are 4 numbers = number of nodes, number of edges, beginning node (where to start), end node (where to end).
On the rest of lines are 3 numbers = one node(lets say x), second node(y), length between them.
The input will give me shortest path between the start and end node.
In this example case it would be number 32.
I have a fully working code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct edge{
int goal, length;
struct edge *p_next;
} EDGE;
typedef struct node{
int name;
EDGE *p_edges, *last;
} NODE;
int helper;
int getDist(int size, NODE *nodes[size+1], int from, int act, int goal)
{
EDGE *p_act;
for(p_act = nodes[act]->p_edges; p_act != 0; p_act = p_act->p_next)
{
if (p_act->goal == goal)
{
return p_act->length;
}
if (p_act->goal != from)
{
helper = getDist(size, nodes, act, p_act->goal, goal);
}
if (helper != 0)
{
return helper + p_act->length;
}
}
return 0;
}
int main()
{
int numV, numH, start, goal, i, length, a, b;
EDGE *p_newEdge, *p_newEdge2;
scanf("%d %d %d %d", &numV , &numH, &start, &goal);
NODE *nodes [numV+1];
for(i = 0; i <= numV; i++)
{
nodes[i] = (NODE*)malloc(sizeof(NODE));
}
for(i = 0; i < numH; i++)
{
scanf("%d %d %d",&a,&b,&length);
p_newEdge = (EDGE*)malloc(sizeof(EDGE));
p_newEdge->length = length;
p_newEdge->goal = b;
p_newEdge2 = (EDGE*)malloc(sizeof(EDGE));
p_newEdge2->length = length;
p_newEdge2->goal = a;
if (nodes[a]->p_edges == 0)
{
nodes[a]->p_edges = p_newEdge;
nodes[a]->last = p_newEdge;
}
else if (nodes[a]->p_edges != 0)
{
nodes[a]->last->p_next = p_newEdge;
nodes[a]->last = nodes[a]->last->p_next;
}
if (nodes[b]->p_edges != 0)
{
nodes[b]->last->p_next = p_newEdge2;
nodes[b]->last = nodes[b]->last->p_next;
}
else if (nodes[b]->p_edges == 0)
{
nodes[b]->p_edges = p_newEdge2;
nodes[b]->last = p_newEdge2;
}
}
printf("%d\n",getDist(numV ,nodes, 0, start, goal));
return 0;
}
But my professor told me that it is very long and I should make it more simple (this was my third attempt and for my professor it is still too long and "complex").
I have no idea how to make it more simple.
Can someone help me with this?
I am trying to write a program that finds a minimum-length path between a two vertices in a graph, selecting from among such paths one of those that traverses the fewest edges. I used Dijkstra's algorithm with several modifications (below).
The output supposed to be: 0->3->4, but instead, my program prints 0->4.
Why do I get the wrong output?
#include<stdio.h>
#include<string.h>
#define INFINITY 9999
#define n 5
#define s 0
#define d 4
void Dijkstra(int Graph[n][n], int _n,int _s, int _d);
int main()
{
int Graph[n][n] = {
{0, 6, 5, 1, INFINITY},
{6, 0, 3, INFINITY, INFINITY},
{5, 3, 0, 2, 5},
{1, INFINITY, 2, 0, 6},
{INFINITY, INFINITY, 5, 6, 0}
};
Dijkstra(Graph,n,s,d);
getchar();
return 0;
}
void Dijkstra(int Graph[n][n], int _n,int _s, int _d)
{
int distance[n], parent[n], visited[n], edge[n]={0}, mindistance,
nextnode= _s, i, j,temp[n][n], res[n];
//parent[] stores the predecessor of each node
//edge[] stores the number of edged of every vertex's shortest path
for (i = 0; i < n; i++) //create the temp matrix
for (j = 0; j < n; j++)
if (Graph[i][j] == INFINITY)
temp[i][j] = INFINITY;
else
temp[i][j] = Graph[i][j];
for(i=0;i<n;i++)
{
distance[i] = INFINITY; //initialize distance
parent[i] = _s; //initialize parent
visited[i] = 0;
if (distance[i] > 0 && distance[i] < INFINITY)
edge[i]++;
}
distance[_s] = 0;
visited[_s] = 1;
while (visited[_d] == 0)
{
//nextnode gives the node at minimum distance
for (i = 0; i < n; i++)
{
mindistance = temp[_s][i] + distance[i];
if (distance[i] < mindistance && !visited[i])
{
mindistance = distance[i];
nextnode = i;
}
}
//check if a better path exists through nextnode
visited[nextnode] = 1;
if (nextnode != _d)
for (i = 0; i < n; i++)
if (!visited[i])
{
if (mindistance + Graph[nextnode][i] < distance[i])
{
distance[i] = mindistance + Graph[nextnode][i];
parent[i] = nextnode;
edge[i] = edge[nextnode] + 1;
}
if (mindistance + Graph[nextnode][i] == distance[i])
{
if (edge[i] >= edge[nextnode] + 1)
{
parent[i] = nextnode;
edge[i] = edge[nextnode] + 1;
}
}
}
}
//print the path
for (i = 0; i < n; i++)
res[i] = 0;
i = nextnode;
while (i != _s)
{
res[i] = parent[i];
i = parent[i];
}
printf("%d", _s);
printf("->");
for (i = 0; i < n; i++)
{
if (res[i] != 0)
{
printf("%d", res[i]);
printf("->");
}
}
printf("%d", _d);
}
You have a couple of problems in the loop where you choose the next node to traverse. It is clearly incorrect to set
mindistance = Graph[_s][i] + distance[i];
on each iteration, since you need mindistance to track the minimum observed distance across iterations. Instead, before the loop you should set
mindistance = INFINITY;
While we're looking at this loop, observe also that you ignore the edge count criterion in selecting the next node to traverse. You need to use that criterion here, too, to ensure that you find a path that meets your criteria.
With those corrections, your program produces the expected output for me.
Do note, by the way, that this is still pretty straight-up Dijkstra. The trick is to recognize that you're implementing a two-component distance measure. The most-significant component is the path length (sum of edge weights), but the edge count is a secondary component by which ties are broken. The implementation therefore looks a little different, but if you factored out the distance comparison and setting to separate functions then you wouldn't be able to tell the remainder apart from standard Dijkstra (simple variation).
I have edited my code, but I still get the same wrong output:
#include<stdio.h>
#include<conio.h>
#define INFINITY 9999
#define n 5
#define s 0
#define d 4
void Dijkstra(int Graph[n][n], int _n,int _s, int _d);
int main()
{
int Graph[n][n]={{0,6,5,1,INFINITY},{6,0,3,INFINITY,INFINITY},{5,3,0,2,5},{1,INFINITY,2,0,6},{INFINITY,INFINITY,5,6,0}};
Dijkstra(Graph,n,s,d);
getchar();
return 0;
}
void Dijkstra(int Graph[n][n],int _n,int _s,int _d)
{
int temp[n][n],distance[n],parent[n],visited[n],mindistance,nextnode,j,i;
//parent[] stores the predecessor of each node
//edge[] stores the number of edges in the shortest path from the source
//create the cost matrix
for(i=0;i<_n;i++)
for(j=0;j<_n;j++)
temp[i][j]=Graph[i][j];
//initialize
for(i=0;i<_n;i++)
{
distance[i]=INFINITY;
parent[i]=_s;
visited[i]=0;
}
distance[_s]=0;
visited[_s]=1;
nextnode=_s;
while(visited[_d]==0)
{
mindistance=INFINITY;
//nextnode gives the node at minimum distance
for(i=0;i<_n;i++)
{
distance[i]=temp[nextnode][i];
if(distance[i]<mindistance && !visited[i])
{
mindistance=distance[i];
nextnode=i;
}
}
//check if a better path exists through nextnode
visited[nextnode]=1;
for(i=0;i<_n;i++)
if(!visited[i])
if(mindistance+temp[nextnode][i]<distance[i])
{
temp[nextnode][i]=mindistance+distance[i];
parent[i]=nextnode;
}
}
//print the path and distance of each node
i=_d;
printf("%d",i);
do
{
i=parent[i];
printf("<-%d",i);
}while(i!=_s);
}
Just a few small changes are needed to get the supposed output; I commented on the code below:
…
distance[_s]=0;
// visited[_s]=1; do not mark the initial node as visited - will select below
// nextnode=_s; no need here - will select as the node at minimum distance
while (!visited[_d])
{
mindistance=INFINITY;
//nextnode gives the node at minimum distance
for (i=0; i<_n; i++)
{
// distance[i]=temp[nextnode][i]; don't change tentative distance here
if (distance[i]<mindistance && !visited[i])
{
mindistance=distance[i];
nextnode=i;
}
}
//check if a better path exists through nextnode
visited[nextnode]=1;
for (i=0; i<_n; i++)
if (!visited[i])
if (mindistance+temp[nextnode][i]<distance[i])
{
// temp[nextnode][i]=mindistance+distance[i]; other way round
distance[i]=mindistance+temp[nextnode][i]; // smaller
parent[i]=nextnode;
}
}
…
For a JPEG image compression, I manipulate image in grey levels and 8bits by pixels
I have this type of matrix I dynamically allocated :
typedef char pixel_t;
pixel_t ** pix_matrix;
after allocating and filling it, I have a bidimensional array with the values (from -128 to +127) of the luminance of the picture.
For the JPEG compression, I need to iterate this array in zigzag like this:
So I want to create an Iterator structure for this type. This iterator must have 'current' and 'begin' members and I want those members to be pointers to the current element and first one of the matrix. In other words, I want to store the addresses and not the indexes. But after hours of tests, prints and researches, I couldn't find the way to make that possible. What type of pointer do I have to use? how make it point to the first address of my matrix? Is my request simply possible?
And if all of this is possible, how can I get the next element, and the value of the current one?
You can write an interator structure:
struct zigzag_t {
int width; // width, must be initialised
int height; // height, must be initialised
int x; // current x index
int y; // current y index
int underway; // dummy value to start at (0, 0)
};
which you must initialise with the width and height of your image. Write an interator function, so that you can use this iterator like this:
struct zigzag_t zz = {8, 8};
while (zigzag_next(&zz)) {
printf("(%d, %d)\n", zz.y, zz.x);
}
The iterator itself is not too complicated: If the sum of the x and y indices is odd, you walk southwest until you hit either the west or south edge. If the sum is even, you walk northeast until you hit either the north or east wall. If you hit the ne or sw edges, the east and south edges get priority. The iteration ends after you have visited the se edge.
Because the struct starts off with x and y both zero, the first point is (0, 1). In order to fix this, the dummy field underway, which also is zero, is used.
The iterator must be reset if you want to use it a second time. better yet, define and initialise a fresh iterator.
The iterator function:
int zigzag_next(struct zigzag_t *zz)
{
int odd = (zz->x + zz->y) % 2;
if (zz->underway == 0) {
zz->x = zz->y = 0;
zz->underway = 1;
return 1;
}
if (odd) {
/* walk southwest */
int w_edge = zz->x == 0;
int s_edge = zz->y == zz->height - 1;
if (s_edge) {
zz->x++;
return zz->x < zz->width;
} else if (w_edge) {
zz->y++;
} else {
zz->x--;
zz->y++;
}
} else {
/* walk northeast */
int e_edge = zz->x == zz->width - 1;
int n_edge = zz->y == 0;
if (e_edge) {
zz->y++;
return zz->y < zz->height;
} else if (n_edge) {
zz->x++;
} else {
zz->x++;
zz->y--;
}
}
return 1;
}
This solution returns the x and y positions, which you can use as indices to your double pointer to pixel data. It would not be hard to extend the struct to hold the base pointer to your pixel data and have the iterator function return a pointer to a pixel or NULL if the iteration has run out.
An example solution with pointers is below.
#include <stdlib.h>
#include <stdio.h>
typedef char pixel_t;
struct zigzag_t {
pixel_t **p; // base data
int width; // width, must be initialised
int height; // height, must be initialised
int x; // current x index
int y; // current y index
int underway; // dummy value to start at (0, 0)
};
pixel_t *zigzag_next(struct zigzag_t *zz)
{
int odd = (zz->x + zz->y) % 2;
if (zz->underway == 0) {
zz->x = zz->y = 0;
zz->underway = 1;
return *zz->p;
}
if (odd) {
/* walk southwest */
int w_edge = zz->x == 0;
int s_edge = zz->y == zz->height - 1;
if (s_edge) {
zz->x++;
if (zz->x == zz->width) return NULL;
} else if (w_edge) {
zz->y++;
} else {
zz->x--;
zz->y++;
}
} else {
/* walk northeast */
int e_edge = zz->x == zz->width - 1;
int n_edge = zz->y == 0;
if (e_edge) {
zz->y++;
if (zz->y == zz->height) return NULL;
} else if (n_edge) {
zz->x++;
} else {
zz->x++;
zz->y--;
}
}
return zz->p[zz->y] + zz->x;
}
int main()
{
pixel_t *data[] = {
"abcde", "fghij", "klmno", "pqrst", "uvwxy"
};
struct zigzag_t zz = {data, 5, 5};
for (;;) {
pixel_t *p = zigzag_next(&zz);
if (p == NULL) break;
putchar(*p);
}
putchar('\n');
return 0;
}
This solution is a C solution. There is no begin member function; initialisation is done via simple struct initialisation. There is no increment operator and no end member function; moving the iterator forward and checking for the end is done in a plain old function.
You have tagged the question C, but iterators are more frequent in C++, where they can be implemented as classes. The above C example may serve as a base for such an implementation.
Something nice and simple.
Function next is the iterator; it returns true until all cells have been visited.
A variable of type POSITION holds the iterator state.
Function current returns a pointer to the current cell in the matrix.
Demo function sample_application puts it all together.
#define MAX_XY 7
typedef struct { int x, y; } POSITION;
static int sign_of(int i)
{
return i < 0 ? -1 : i > 0 ? 1 : 0;
}
static int get_direction(int a, int b, int odd_is_forward)
{
return sign_of(((a + b) % 2 == odd_is_forward || b >= MAX_XY ? MAX_XY : 0) - a);
}
int next(POSITION *pos)
{
int x = pos->x;
int y = pos->y;
pos->x += get_direction(x, y, 0);
pos->y += get_direction(y, x, 1);
return x < MAX_XY || y < MAX_XY;
}
pixel_t *current(POSITION *pos)
{
return &pix_matrix[pos->y][pos->x];
}
void sample_application() // just demonstrating the use of POSITION
{
POSITION pos = {-1, -1}; // always start from these dummy coordinates
while (next(&pos)) // this iterates through the matrix
{
int coord_x = pos.x; // this is how you get the current coordinates
int coord_y = pos.y;
*current(&pos) = 12; // this is how you access the current cell
}
}
I'm trying to replace cycle in the graph to a group of the vertexes (remove this cycle and put there once vertex with maximum number)
struct group {
int master; // representative of cycle
};
struct vertex {
int *to; // neighbor list
int nb; // how many neighbor
int p; // parent
short v; // was visited? 0 = false, 1 = true
struct group *cycle; // is part of cycle? NULL = no, else pointer to group
};
I'm running dfs on each vertex
void searchCycles() {
int i;
for (i = 0; i < MAX_VER; i += 1)
if (ver[i].v == 0 && ver[i].nb > 0)
dfs(i);
}
dfs:
void dfs(int v) {
ver[v].v = 1;
int i;
for (i = 0; i < ver[v].nb; i += 1) {
ver[ver[v].to[i]].p = v;
if (ver[ver[v].to[i]].v == 0)
dfs(ver[v].to[i]);
else
// cycle found
replaceCycle(ver[v].to[i]);
}
}
and replace function shout print what vertexes are in cycle
void replaceCycle(int v) {
struct group *g = &gr[usedGroup++];
g->master = -1;
printf("\nCYKL: %d ", v);
int p = ver[v].p;
while (p != v) {
printf("%d(%d) ", p, v);
p = ver[p].p;
}
printf("\n");
}
Generally it's works, but sometimes it get a infinity loop. I tried to debug it and if there are two or more cycles, parents (p in vertex struct) are lost, it's means it works fine but there is wrong number. I'm learning C and algorithms, so I don't know a lot of it.
It's not a homework, it's a spoj problem
Once you replace a cycle, restart your dfs.
Basically, the visited flag might be set for your first cycle, but you'd want that cleared to test your second cycle. (And third, and fourth, etc.)