I am trying to use a DFS algorithm to calculate the distance from a source node for each node. Currently it outputs a distance of 0 for the source vertex but 1 for all the other vertices, even though there should be a couple with a distance of 2. The printf in the DFS does print out the right order, with the source first then the vertices with distance 1 and then distance 2. So where in the algorithm would I need to put the distance increase.
void dfs(int vertex1) {
graph[vertex1-1].visited = 1;
printf("%d \n",vertex1);
struct edge *e;
e = graph[vertex1-1].edgePtr;
while (e) {
if (!(graph[e->vertexIndex - 1].visited)){
graph[e->vertexIndex - 1].distance++;
dfs(e->vertexIndex);
}
e = e->edgePtr;
}
}
I think I have figured out a way to make the DFS calculate the distance and it is correct except the last vertex found it says that the distance is 3 instead of 2.
5
(2,3)
(1,4)
(1,3)
(3,4)
(4,5)
#include <stdio.h>
#include <stdlib.h>
#include "../HW3/input_error.h"
#define VertexToSearch 1
typedef struct edge {
int vertexIndex;
struct edge *edgePtr;
} edge;
typedef struct vertex {
int vertexKey;
struct edge *edgePtr;
int visited;
int distance;
} vertex;
int vertexCount = 0;
struct vertex graph[];
void load_file(char*);
void insertEdge(int, int, struct vertex[]);
void InsertVertex(int, struct vertex[]);
void printGraph();
void dfs();
void print_distances();
enum error program_error;
int count;
int main(int argc, char** argv) {
load_file(argv[1]);
printGraph();
dfs(VertexToSearch);
print_distances();
return 0;
}
void load_file(char* filename) {
int vertex1;
int vertex2;
FILE* file = fopen(filename, "r");
if (file == NULL) {
printf("%s did not open\n", filename);
program_error = FILE_FAILED_TO_OPEN;
exit(program_error);
}
fscanf(file, "%d", &count);
graph[count];
for (int i = 0; i < count; i++) {
InsertVertex(i+1, graph);
}
for (int i = 0; i < count; i++) {
fscanf(file, "\n(%d,%d)", &vertex1, &vertex2);
insertEdge(vertex1, vertex2, graph);
}
fclose(file);
}
void InsertVertex(int vertexKey, struct vertex graph[]) {
graph[vertexCount].vertexKey = vertexKey;
graph[vertexCount].edgePtr = NULL;
graph[vertexCount].visited = 0;
graph[vertexCount].distance = 0;
vertexCount++;
}
void insertEdge(int vertex1, int vertex2, struct vertex graph[]) {
struct edge *e, *e1, *e2;
e = graph[vertex1 - 1].edgePtr;
while (e && e->edgePtr) {
e = e->edgePtr;
}
e1 = (struct edge *) malloc(sizeof (*e1));
e1->vertexIndex = vertex2;
e1->edgePtr = NULL;
if (e)
e->edgePtr = e1;
else
graph[vertex1 - 1].edgePtr = e1;
e = graph[vertex2 - 1].edgePtr;
while (e && e->edgePtr) {
e = e->edgePtr;
}
e2 = (struct edge *) malloc(sizeof (*e2));
e2->vertexIndex = vertex1;
e2->edgePtr = NULL;
if (e)
e->edgePtr = e2;
else
graph[vertex2 - 1].edgePtr = e2;
}
void printGraph() {
int i;
struct edge *e;
for (i = 0; i < vertexCount; i++) {
printf("%d(%d)", i+1, graph[i].vertexKey);
e = graph[i].edgePtr;
while (e) {
printf("->%d", e->vertexIndex);
e = e->edgePtr;
}
printf("\n");
}
}
void dfs(int vertex1) {
graph[vertex1 - 1].visited = 1;
printf("%d \n", vertex1);
struct edge *e;
e = graph[vertex1 - 1].edgePtr;
for (int i = 0; i < count; i++) {
if (graph[i].visited == 0 && e->vertexIndex != VertexToSearch) {
graph[i].distance++;
}
}
while (e) {
if (!(graph[e->vertexIndex - 1].visited)) {
dfs(e->vertexIndex);
}
e = e->edgePtr;
}
}
void print_distances(){
for(int i = 0;i < count; i++){
printf("%d %d\n", i+ 1,graph[i].distance);
}
}
Related
Hi everyone so i got this task to make an adt of non-binary tree which can do traversals. I messed up the structure from the very beginning but I still can do the post-order and pre-order traversal (i don't know if i did it wrong too, but it works). Now i confused how to do the in-order traversal. My code just doesn't work.
This is my data structure
typedef char infotype;
typedef int letak;
typedef struct {
infotype info;
letak parent, firstson, nextsibling;
} node;
typedef node tree;
These are how I initialize each node
void initNode(tree T[], int k, int i)
{
char info;
printf("Input the node name : ");
scanf(" %c", &info);
createNode(T, k, i, info);
}
void createNode(tree T[], int k, int i, char value)
{
int j;
if(i == 0)
{
T[i].info = value;
T[i].firstson = i+1;
}
else
{
T[i].info = value;
T[i].parent = (i-1) / k;
T[i].firstson = (i * k) + 1;
if (i % k != 0)
{
T[i].nextsibling = i+1;
}
else
{
T[i].nextsibling = 0;
}
}
}
and this is how I try to do the in-order traversal
void InOrder(tree T[], int maksimum_array, int maksimum_anak)
{
bool Resmi = true;
int i = 0;
while(i >= 0)
{
if(T[i].firstson < maksimum_array - 1 && Resmi == true)
{
i = T[i].firstson;
}
else
{
if(Resmi == true)
{
printf("%c ", T[i].info);
}
if(i = T[T[i].parent].firstson)
{
printf("%c ", T[T[i].parent].info);
}
if(T[i].nextsibling < maksimum_array - 1 && T[i].nextsibling != 0)
{
i = T[i].nextsibling;
Resmi = true;
}
else
{
i = T[i].parent;
Resmi = false;
}
}
}
}
And this is my main driver :
int main()
{
tree pohon[1000];
int maksimum;
int maksimum_anak;
int level;
int i = 0;
int count = 0;
char cari;
printf("Enter array maximum amount : ");
scanf("%d", &maksimum);
printf("\nEnter maximum child of each node : ");
scanf("%d", &maksimum_anak);
createTree(pohon);
for (i = 0; i < maksimum ; i++)
{
initNode(pohon, maksimum_anak, i);
}
for (i = 0; i < maksimum; i++)
{
printTree(pohon, i, maksimum, maksimum_anak);
}
printf("In Order Traversal : ");
InOrder(pohon, maksimum, maksimum_anak);
}
I've tried another algorithms for the in-order traversal like using recursive. But since i messed up the struct those algorithms just did not work. Thank you before.
if(i = T[T[i].parent].firstson)
Should be
if(i == T[T[i].parent].firstson)
The former assigns to i, the latter compares it.
I do not know why this is not working.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// struct of list
typedef struct noeud
{
int adresse, taille, temp;
struct noeud* suivant;
} * liste;
int random(int a, int b)
{
return (a + (rand() % ((b + 1) + a)));
}
void initialisation(liste* LBO)
{
*LBO = NULL;
}
I think it's here the problem when I create q (q is created to point to the previous node).
void creation(liste* LBO)
{
liste q, prec = NULL;
int i = 0;
srand(time(NULL));
while (i < 3)
{
printf("%d", i);
q = malloc(sizeof(liste));
if (*LBO == NULL)
{
q->adresse = 0;
q->taille = random(5, 45);
q->temp = random(5, 15);
q->suivant = *LBO;
*LBO = q;
i++;
}
else
{
prec = *LBO;
q->taille = random(5, 45);
q->temp = random(5, 15);
q->adresse = prec->adresse + prec->taille;
q->suivant = *LBO;
*LBO = q;
i++;
}
}
}
void affichage(liste LBO)
{
printf("\nvoici ta liste \n ");
while (LBO != NULL)
{
printf("%d-->", LBO->taille);
LBO = LBO->suivant;
}
if (LBO == NULL)
printf("NULL");
}
int main()
{
// or here
printf("Hello world!\n");
liste LBO;
initialisation(&LBO);
creation(&LBO);
affichage(LBO);
return 0;
}
There are several issues:
Instead of calling
initialisation(&LBO);
which is not really wrong, just write:
LBO = NULL;
Then don't hide pointers with typedefs, it only adds confusion.
Instead of:
typedef struct noeud
{
int adresse, taille, temp;
struct noeud* suivant;
} *liste;
Write:
struct noeud
{
int adresse, taille, temp;
struct noeud* suivant;
};
and use struct noeud* instead of liste.
Now the real problem:
This is wrong. Here you allocate the size for a pointer, but you need to allocate the size for the whole structure:
q = malloc(sizeof(liste));
which is actually the same as:
q = malloc(sizeof(struct noeud*))
but you need:
q = malloc(sizeof(struct noeud))
You see now why hiding pointers with typedefs is a bad idea.
So here is the corrected version of your program (#includes ommitted for brevity):
struct noeud
{
int adresse, taille, temp;
struct noeud* suivant;
};
int random(int a, int b)
{
return (a + (rand() % ((b + 1) + a)));
}
void creation(struct noeud** LBO)
{
struct noeud* q, *prec = NULL;
int i = 0;
// srand(time(NULL)); <<<<< don't call srand here, call it once at the
// beginning of the program
while (i < 3)
{
printf("%d", i);
q = malloc(sizeof(struct noeud));
if (*LBO == NULL)
{
q->adresse = 0;
q->taille = random(5, 45);
q->temp = random(5, 15);
q->suivant = *LBO;
*LBO = q;
i++;
}
else
{
prec = *LBO;
q->taille = random(5, 45);
q->temp = random(5, 15);
q->adresse = prec->adresse + prec->taille;
q->suivant = *LBO;
*LBO = q;
i++;
}
}
}
void affichage(struct noeud* LBO)
{
printf("\nvoici ta struct noeud* \n ");
while (LBO != NULL)
{
printf("%d-->", LBO->taille);
LBO = LBO->suivant;
}
// if (LBO == NULL) <<<<<<<<<<< drop this, LBO is always NULL here
// but it doesn't hurt, it's just useless
printf("NULL");
}
int main()
{
srand(time(NULL)); // <<<<<<<<<<<<< call srand here
struct noeud* LBO;
LBO = NULL;
creation(&LBO);
affichage(LBO);
return 0;
}
There is still room for improvement, especially the creation function is somewhat awkward.
Also look at the comments with <<<<<<<<<<<, there are minor corrections
I have a program in C which reads definition of graph from file, search for Hamiltonian cycle (only one) and prints it on screen if found. Problem is that program is crashing when I'm trying to find cycle in graphs with 30 and more vertices (for 30 vertices it sometimes shows cycle end get crashed (with different saturations), for more get crashed instantly). When I try to debug it stops at free() function and shows SIGTRAP signal. What can I do to fix that? Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
typedef struct Lista
{
struct Lista * next;
int v;
} Lista;
Lista * stos;
bool *visited;
int wierzcholki, krawedzie;
int *S;
int sptr;
Lista **graf;
bool czyZnaleziono = false;
int DFSHamilton(int v)
{
if (!czyZnaleziono)
{
int i;
bool test;
Lista *p;
S[sptr++] = v;
if(sptr < wierzcholki)
{
visited[v] = true;
for(p = graf[v]; p; p = p->next)
if(!visited[p->v]) DFSHamilton(p->v);
visited[v] = false;
}
else
{
test = false;
for(p = graf[v]; p; p = p->next)
if(!(p->v))
{
test = true;
break;
}
if(test)
{
printf("Hamiltonian Cycle : ");
for(i = 0; i < sptr; i++)
{
printf("%d ",S[i]);
}
printf("0\n");
czyZnaleziono = true;
}
}
sptr--;
}
}
int main()
{
FILE *plik;
Lista *p, *r;
plik = fopen("rzeczy40-95.txt", "r");
double start, stop, czas;
int i, j, w1, w2;
sptr = 0;
visited = malloc(krawedzie*sizeof(bool));
if (plik == NULL)
{
printf("Nie mozna odnalezc pliku");
return 0;
}
else
{
fscanf(plik, "%d %d", &wierzcholki, &krawedzie);
S = malloc(wierzcholki*sizeof(int));
graf = malloc(wierzcholki*sizeof(Lista));
for(i=0; i<wierzcholki; i++)
{
graf[i] = NULL;
visited[i] = false;
}
for(j=0; j<krawedzie; j++)
{
fscanf(plik,"%d %d", &w1, &w2);
p = malloc(sizeof(Lista));
r = malloc(sizeof(Lista));
p->v = w2;
p->next = graf[w1];
graf[w1] = p;
r->v = w1;
r->next = graf[w2];
graf[w2] = r;
}
fclose(plik);
DFSHamilton(0);
free(visited);
free(S);
for (i = 0; i < wierzcholki; i++)
{
free(graf[i]);
}
free(graf);
return 0;
}
}
So I'm having trouble with Dijkstra's algorithm (src to dest). I looked at other answers and could not find the solution to my problem. I have used an adjacency list, thus I have a list for vertices, and each vertex has it's own edge list. My problem arises when I have a node that is unreachable. Specifically, it never gets visited thus I'm stuck in my allNotComp while loop. Can anyone help me with a solution? Code is below.
#include <stdlib.h>
#include <stdio.h>
int INFINITY = 9999;
struct edge
{
int vertexIndex;
int vertexWeight;
struct edge *edgePtr;
} edge;
struct vertex
{
int vertexKey;
struct edge *edgePtr;
struct vertex *vertexPtr;
}vertex;
struct vertex *Start = NULL;
void insertEdge(int vertex, int vertex2, int vertexWeight);
void insertVertex(int vertexKey);
int allNotComp(int comp[], int size);
void printPath(int prev[], int src, int dest, int size);
void dijkstra(int src, int size, int dest);
int cost(int curr, int i);
int main(int argc, char * argv[]) {
int k = 1;
int numVertices = atoi(argv[2]);
char* source = argv[3];
char* destination = argv[4];
int src = atoi(argv[3]);
int dest = atoi(argv[4]);
Start = &vertex;
Start->vertexKey = 0;
Start->vertexPtr = NULL;
Start->edgePtr = NULL;
int m = 0;
int flag = 0;
int flag2 = 0;
for(m = 0; m < numVertices; m++){
if(src == m) {
flag = 1;
}
if(dest == m) {
flag2 = 1;
}
}
if(!(flag && flag2)) {
printf("%s ", "ERROR: Src and/or Dest not valid.\n");
exit(0);
}
while(k < numVertices) {
insertVertex(k);
k++;
}
FILE *f = fopen(argv[1], "r");
int numbers[numVertices][numVertices];
char ch;
int i = 0;
int j = 0;
for(m = 0; m < numVertices*numVertices; m++) {
fscanf(f, "%d", &(numbers[i][j]));
j=j+1;
if(j == numVertices) {
i=i+1;
j=0;
}
}
for(i=0;i<numVertices;i++) {
for(j=0;j<numVertices;j++) {
if(i == j && numbers[i][j] != 0) {
printf("%s", "ERROR: All diagonals must be zero.\n");
exit(0);
}
if(i != j) {
insertEdge(i, j, numbers[i][j]);
}
}
}
dijkstra(src, numVertices, dest);
}
void insertEdge(int vertex, int vertex2, int vertexWeight)
{
if(vertexWeight == -1) return;
struct vertex *traverse;
if(vertex == Start->vertexKey) {
traverse = Start;
}
else {
while(traverse->vertexKey != vertex) {
traverse = traverse->vertexPtr;
}
}
struct edge *e,*e1,*e2;
e=traverse->edgePtr;
while(e&& e->edgePtr)
{
e=e->edgePtr;
}
e1=(struct edge *)malloc(sizeof(*e1));
e1->vertexIndex=vertex2;
e1->vertexWeight = vertexWeight;
e1->edgePtr=NULL;
if(e)
e->edgePtr=e1;
else
traverse->edgePtr=e1;
}
void insertVertex(int vertexKey) {
struct vertex *v, *v1, *v2;
v = Start->vertexPtr;
while(v && v->vertexPtr) {
v=v->vertexPtr;
}
v1=(struct vertex *)malloc(sizeof(*v1));
v1->vertexKey = vertexKey;
v1->vertexPtr = NULL;
v1->edgePtr = NULL;
if(v) {
v->vertexPtr = v1;
}
else {
Start->vertexPtr = v1;
}
}
void dijkstra(int src, int size, int dest) {
int comp[size];
int dist[size];
int prev[size];
int i;
for(i = 0; i<size; i++) {
comp[i] = 0;
dist[i] = INFINITY;
prev[i] = -1;
}
comp[src] = 1;
dist[src] = 0;
prev[src] = src;
int curr = src;
int k;
int minDist;
int newDist;
while(allNotComp(comp, size)) {
minDist = INFINITY;
for(i = 0; i<size;i++) {
if(comp[i] == 0) {
newDist = dist[curr] + cost(curr, i);
if(newDist < dist[i]) {
dist[i] = newDist;
prev[i] = curr; }
if(dist[i] < minDist) {
minDist = dist[i];
k=i; }
}
}
curr = k;
comp[curr] = 1;
}
if(dist[dest] < INFINITY) {
printPath(prev, src, dest, size);
printf(":%d\n", dist[dest]);
} else {
printf("%s\n", "NO PATH EXISTS BETWEEN THE TWO VERTICES!");
}
}
int allNotComp(int comp[], int size) {
int i;
for(i = 0; i < size; i++) {
if(comp[i] == 0) {
return 1;
}
}
return 0;
}
int cost(int curr, int i) {
struct vertex *travel;
struct edge *traverse;
travel = Start;
while(travel->vertexPtr != NULL) {
if(travel->vertexKey != curr) {
travel = travel->vertexPtr;
}
else{
break;
}
}
traverse = travel->edgePtr;
while(traverse->edgePtr != NULL) {
if(traverse->vertexIndex != i) {
traverse = traverse->edgePtr;
}
else{
break;
}
}
if(traverse->vertexIndex != i) {
return INFINITY;
}
return traverse->vertexWeight;
}
void printPath(int prev[], int src, int dest, int size) {
if(src == dest) {
printf("%d", src);
}
else {
printPath(prev, src, prev[dest], size);
printf("-%d", dest);
}
}
Although an unreachable node never gets visited, this situation can be detected. If the dists of all unvisited nodes are INFINITY, this means all remaining nodes are unreachable, and you should end the loop.
The following code displays my created binary tree from left to right on the console window. How do I print it from the top to the bottom, as you would on paper?
// Binary Trees Implementation
#include<stdio.h>
#include<stdlib.h>
typedef struct BTNode
{
int key;
struct BTNode *left, *right;
};
void displayBT(BTNode *p, int level);
BTNode *buildBT();
void RSD(BTNode *p);
void SRD(BTNode *p);
void SDR(BTNode *p);
int main()
{
int op;
BTNode *root;
do
{
printf("\n 1. Build Binary Tree");
printf("\n 2. Display Binary Tree");
printf("\n 3. Display Traversals");
printf("\n 0. Exit");
printf("\n........................\n");
scanf("\n %d", &op);
switch(op)
{
case 1:
root=buildBT();
break;
case 2:
displayBT(root,0);
break;
case 3:
printf("\n Pre-Order:");
RSD(root);
printf("\n In-Order:");
SRD(root);
printf("\n Post-Order:");
SDR(root);
printf("\n.....................\n");
break;
}
} while(op);
}
BTNode *buildBT()
{
int value;
BTNode *p;
printf("\n k=");
scanf("%d",&value);
if(value!=0)
{
p=(BTNode *)malloc(sizeof(BTNode));
p->key = value;
p->left = buildBT();
p->right = buildBT();
} else p=NULL;
return p;
}
void displayBT(BTNode *p, int level)
{
if(p!=NULL)
{
displayBT(p->right, level+1);
for(int j=0; j<=level;j++)
printf(" ");
printf("%d \n", p->key);
displayBT(p->left, level+1);
}
}
void RSD(BTNode *p)
{
if(p!=NULL)
{
printf("%d ", p->key);
RSD(p->left);
RSD(p->right);
}
}
void SRD(BTNode *p)
{
if(p!=NULL)
{
SRD(p->left);
printf("%d ", p->key);
SRD(p->right);
}
}
void SDR(BTNode *p)
{
if(p!=NULL)
{
SDR(p->left);
SDR(p->right);
printf("%d ", p->key);
}
}
Ok so I uploaded the full code because I was having trouble with the suggestions and maybe I should have done this from the beginning.
gave it another go, actually tried it now. works for me
void print_box(FILE* out, int i)
{
static char buff[16] = {0};
sprintf(buff,"%d",i);
int n = strlen(buff);
static char buf2[16] = {0};
strcpy(buf2,"[ ]");
int nn = 2 - (n-1)/2 ;
for(i=0;i<n;++i)
buf2[nn+i] = buff[i];
fprintf(out,"%s",buf2);
}
void print_empty_box(FILE* out) { fprintf(out,"%s","[ - ]"); }
typedef struct NodeRowTag
{
struct NodeRowTag* nxt;
BTNode* node;
} NodeRow;
NodeRow* make_head()
{
NodeRow* nr;
nr = (NodeRow*) malloc(sizeof(NodeRow));
nr->node = 0;
nr->nxt = 0;
return nr;
}
void push_back( NodeRow* nr, BTNode* n )
{
while( nr->nxt )
{
nr = nr->nxt;
}
nr->nxt = (NodeRow*) malloc(sizeof(NodeRow));
nr->nxt->node = n;
nr->nxt->nxt = 0;
}
void del_all( NodeRow* nr )
{
if( nr->nxt )
del_all(nr->nxt);
free( nr );
}
NodeRow* print_and_next( FILE* out, NodeRow* nr, int rownum, int maxnum )
{
// init spacing
int spacing = 0;
int stride = 3;
for(int i=rownum; i<maxnum; ++i)
{
spacing += stride;
stride *= 2;
}
for(int i=0;i<spacing;++i)
fprintf(out, " " );
// inbetween spacing
spacing = 1;
stride = 6;
for(int i=rownum; i<maxnum; ++i)
{
spacing += stride;
stride *= 2;
}
//
NodeRow* nxt = make_head();
NodeRow* n = nr->nxt;
while(n)
{
BTNode* p = n->node;
if(p) {
print_box(out,p->key);
push_back(nxt,p->left);
push_back(nxt,p->right);
} else {
print_empty_box(out);
push_back(nxt,0);
push_back(nxt,0);
}
for(int i=0;i<spacing;++i)
fprintf(out, " " );
n=n->nxt;
}
fprintf(out, "\n" );
del_all(nr);
return nxt;
}
int max(int a,int b) { return (a>b)?a:b; }
int max_depth( BTNode* p )
{
if(!p) return 0;
return 1 + max( max_depth(p->left), max_depth(p->right) );
}
void PrittyPrint( FILE* out )
{
int n = max_depth(root);
NodeRow* nr = make_head();
push_back(nr,root);
for(int i=1; i<=n; ++i)
{
nr = print_and_next( out, nr, i, n );
}
del_all(nr);
}
By printing the value of the current node BEFORE recursing right/left!