I am trying to figure out how to write BFS algorithm in C
and I got this
typedef struct graph {
int numnodes;
int **edges;
} graph;
void bfs(graph *g, int start) {
int visited[g->numnodes], queue[g->numnodes], front =- 1, rear =- 1;
for (int i = 0; i < g->numnodes; i++) {
visited[i] = 0;
}
front++;
queue[++rear] = start;
visited[start] = 1;
while (front <= rear) {
start = queue[front++];
printf("%d\t", start);
for (int i = 0; i < g->numnodes; i++) {
if (g->edges[start][i] == 1 && !visited[i]) {
queue[++rear] = i;
}
}
}
}
for graph looking like graph.
When I print out BFS, it seems to give me
0 1 2 2 3 4
I'm not entirely sure what's wrong here, some help would be appreciated.
I am not sure if BFS is the right term for what you are doing. Your graph is not a tree and with a node having multiple parent nodes it is hard to tell on what level a node really is.
But to make your code work as expected, you just need to fix your missing use of visited array:
if (g->edges[start][i] == 1 && !visited[i]) {
queue[++rear] = i;
visited[i] = 1;
}
Create an actual graph and go through that (e.g. struct for each node, nodes linked via pointers). Right now what you have is an array that you go through item by item if I understand correctly.
You can use an array to store one level of the graph.
0 (first level)
2 1 (second level)
...
Related
(1 mo into learning c) I've been learning about making/using ADT lists and learned the basic functions(used for making ADT lists) like 'count', 'concatenate', 'insert' and etc. And i had an (online course)assignment that required me to bubblesort an ADT list.
So I kinda implemented what I knew about bubblesorting an array to the ADT list. Normally bubblesorting an array looks like this:
void bubbleSort(int arr[], int n) { //int n = numb of elements in the array
int i, j;
for (i = 0; i < n-1; i++) {
for (j = 0; j < n-i-1; j++)
if (arr[j] > arr[j+1])
swap(&arr[j], &arr[j+1]); //assuming 'swap(a,b);' swaps the two elements
}
}
So simply i 'just' implemented the modified 'swap' function and that was what i did like the below code. (I couldn't really think of a better method, tried anything what i could do)
typedef struct list { int data; struct list *next; } list;
...//some portion of the code fills/links the nodes
void bubblesort(list* p) {
list* pn = p->next;
for (i = 0; i < SIZE - 1; i++) {
for (j = 0; j < SIZE - j - 1; j++) {
if (p->data > pn->data) // Exception ERR here
datSwap(p, pn); // just swaps (only)the data portion of the two nodes(in ADT lists)
p = pn;
pn = pn->next;
if (pn == NULL)
break;
}
}
}
I'm pretty sure this code isn't pretty and it certainly doesn't work(Exception thrown: read access violation. 'pn' was nullptr.).
When I looked into the problem I thought that in normal situations when using arrays(the 1st code) 'j' used in arrays like 'arr[j+1]' would reset to the starting point(arr[0]) once the for loop was done, but ADT lists not having such 'positions(?)' ended up not resetting the position to the beginning(or to the head) which caused the 'np' to be NULL. So in my theory either the 'p' needed to be reset to the head by reversing up the list(which to my knowledge I don't know how to) or the bubblesort() function needs to be redesigned.
So, my question is...
Can I change the 'pointer of the ADT list'(Am i phrasing this right?) which is at the tail to the head? Image for explanation(idk whether people can understand what i'm saying or not so i included an image)
I know how to progress into a list like the following code which prints a list using 'p = p->data' like below but i want to know if i can do it the opposite way or not
typedef struct list { int data; struct list *next; } list;
...//some portion of the code fills/links the nodes
void printList(list* p) {
int i = 0;
while (p != NULL) {
printf("%d", p->data);
p = p->next;
if (p == NULL)
break;
else
printf(" : "); i++; if (i % 10 == 0 && i > 0) { printf("\n"); }
}
}
if not, how can i change/improve the 'bubblesort' function to sort the lists?
Thank you and if I said something wrong please correct me.
Try to reformulate the inner loop to iterate over p list from the first to "before last" element.
for (list *j = p; j->next; j = j->next)
if (j->data > j->next->data)
datSwap(j, j->next);
Im trying to sort, using Insertion Sort, variable-length array of pointers to struct objects.
The sorting criteria is based on the structs distance_to_neighbor attribute.
The problem is it seems that sorted output is semi-sorted.
Here is my data structure for a tree node:
typedef struct tree_
{
struct tree *left;
struct tree *right;
float * info;
float distance_to_neighbor;
} tree;
Here is my Insertion Sort implementation, relevant code snippet (based on https://www.techiedelight.com/insertion-sort-iterative-recursive/):
// perform insertion sort on array of references to structs
void insertion_sort(tree ** arr, int n)
{
// Start from second element (element at index 0
// is already sorted)
tree * pre_value = NULL;
for (int i = 1; i < n; i++)
{
tree * value = *(arr + i);
int j = i;
// Find the index j within the sorted subset arr[0..i-1]
// where element arr[i] belongs
pre_value = *(arr + j - 1);
while (j > 0 && pre_value->distance_to_neighbor > value.distance_to_neighbor)
{
**(arr + j) = **(arr + j - 1);
j--;
}
// Note that subarray arr[j..i-1] is shifted to
// the right by one position i.e. arr[j+1..i]
**(arr + j) = value;
}
}
Code snippet used for debugging before & after sort:
printf ("debug {");
float * info;
float distance = 0;
for (int c = 0; c < k_dimensions; c++)
{
info = (float *) current->info;
if (NULL != info)
{
printf ("%f,", info[c]);
}
else
{
break;
}
}//end for
printf ("} ");
distance = (float) current->distance_to_neighbor;
printf ("distance_to_neighbor=%f\n", distance);
Here are the values before sorting (should be sorted based on distance_to_neighbor) :
debug {-50.000000,-50.000000,-50.000000,} distance_to_neighbor=53.000000
debug {-3.000000,-3.000000,-3.000000,} distance_to_neighbor=6.000000
debug {-2.000000,-2.000000,-2.000000,} distance_to_neighbor=5.000000
debug {-1.000000,-1.000000,-1.000000,} distance_to_neighbor=4.000000
debug {0.000000,0.000000,0.000000,} distance_to_neighbor=3.000000
debug {1.000000,1.000000,1.000000,} distance_to_neighbor=2.000000
debug {2.000000,2.000000,2.000000,} distance_to_neighbor=1.000000
debug {3.000000,3.000000,3.000000,} distance_to_neighbor=0.000000
debug {4.000000,4.000000,4.000000,} distance_to_neighbor=1.000000
debug {5.000000,5.000000,5.000000,} distance_to_neighbor=2.000000
debug {6.000000,6.000000,6.000000,} distance_to_neighbor=3.000000
debug {7.000000,7.000000,7.000000,} distance_to_neighbor=4.000000
debug {8.000000,8.000000,8.000000,} distance_to_neighbor=5.000000
debug {100.000000,100.000000,100.000000,} distance_to_neighbor=97.000000
After sorting (looks sorted descending order then suddenly ascending order!. It should only be ascending order):
{8.000000,8.000000,8.000000,} distance_to_neighbor=5.000000
{7.000000,7.000000,7.000000,} distance_to_neighbor=4.000000
{6.000000,6.000000,6.000000,} distance_to_neighbor=3.000000
{5.000000,5.000000,5.000000,} distance_to_neighbor=2.000000
{4.000000,4.000000,4.000000,} distance_to_neighbor=1.000000
{3.000000,3.000000,3.000000,} distance_to_neighbor=0.000000
{2.000000,2.000000,2.000000,} distance_to_neighbor=1.000000
{1.000000,1.000000,1.000000,} distance_to_neighbor=2.000000
{0.000000,0.000000,0.000000,} distance_to_neighbor=3.000000
{-1.000000,-1.000000,-1.000000,} distance_to_neighbor=4.000000
{-2.000000,-2.000000,-2.000000,} distance_to_neighbor=5.000000
{-3.000000,-3.000000,-3.000000,} distance_to_neighbor=6.000000
{-50.000000,-50.000000,-50.000000,} distance_to_neighbor=53.000000
{100.000000,100.000000,100.000000,} distance_to_neighbor=97.000000
I must keep my function signature the same as void insertion_sort(tree ** arr, int n). How can I fix this sorting bug?
Thanks
You seem to assume that pre-value changes as you change j, but it needs to be re-calculated with each change to j.
I'm trying to sort a doubly linked list, but I'm having some trouble. I'm a noob in C and I guess my problem is with pointers..
I just can't see how to swap two positions inside the list and so maybe that's the issue.
I tryied to sort it by using Bubblesort, even knowing that it's complexity is not so good because, how I'm still learning, thought that it was an easy way to start.
I also tryied reading some things about swaping elements in a linkedlist and how to sort them, but I'm really stuck with this problem...
PS: I started the for with the m->next cause my list has a header(m).
PS2:I'm getting the error "request for member ‘next’ in something not a structure or union", and don't know how to fix it
struct segment {
int x, y; /// position
char c; // letter
struct segment* next;
struct segment* prev;
};
void sortingSegments(struct segment* m) {
struct segment **j; struct segment **i;
for(i = &((m->next)->next); i !=NULL; i = i->next) {
for(j = &(m->next); j == i; j = j->next) {
if ((*j)->c > (*i)->c) {
struct segment **aux;
aux = i;
(*aux)->next = (*i)->next;
(*aux)->prev = (*i)->prev;
i = j;
(*i)->next = (*j)->next;
(*i)->prev = (*j)->prev;
j = aux;
(*j)->prev = (*aux)->prev;
(*j)->next = (*aux)->next;
}
}
}
}
Please read the comments and try to understand the linking of nodes.
It is based on the simple bubble sort described in wikipedia.
void sortingSegments(struct segment** m) {
struct segment *i, *tmp, *prev, *next;
int swapped = 1;
/*
* https://en.wikipedia.org/wiki/Bubble_sort#Pseudocode_implementation
* n = length(A)
* repeat
* swapped = false
* for i = 1 to n-1 inclusive do
* //if this pair is out of order
* if A[i - 1] > A[i] then
* // swap them and remember something changed
* swap(A[i - 1], A[i])
* swapped = true
* end if
* end for
* until not swapped
*/
// looping until no more swaps left
while (swapped) {
swapped = 0;
// we begin from the second item at each iteration
for (i = (*m)->next; i; i = i->next) {
// we need to swap i with i->prev
if (i->prev->c > i->c) {
prev = i->prev;
next = i->next;
// swapping first and second elements,
// so update m to reflect the change made
// to the head of the list
if (prev == *m) {
*m = i;
}
// so there is a prev of prev, update that two links
else {
prev->prev->next = i;
i->prev = prev->prev;
}
// so there is a next, update that two links
if (next) {
next->prev = prev;
prev->next = next;
}
// no next element, mark the end of the list
else {
prev->next = NULL;
}
// this is obvious, prev now becomes i's next
prev->prev = i;
i->next = prev;
// this is needed to reflect the change in i
i = prev;
swapped = 1;
}
}
}
}
I have three nodes as follows.
First node (sNodes) contains: a,b,c,d
Second node (rNodes) contains: c,d,e,f
Third node (nodes) contains: a,b,c,d
I want to add any nodes from second node that is not in the third node. I am having hard time how to do it in C as I am just a beginner. I tried using strcmp method in for loop but couldn't solve it that way. Any help would be really appreciated.
typedef struct {
char emails[(LENGTH*2)+1];
}Node;
Node nodes[GRAPH_SIZE + 1], sNodes[(GRAPH_SIZE + 1) / 2], rNodes[(GRAPH_SIZE + 1)/2];
void addNode(){
int j =0,k = 0, compare, total;
char item[] = {0};
for(j = 0; j <= GRAPH_SIZE/2; j++){
total = 0;
for(k = 0; k <= GRAPH_SIZE/2; k++){
if(strcmp(rNodes[j].emails, nodes[k].emails) != 0){
total = 1;
}else {
total = 0;
}
}
if(total == 1){
strcpy(nodes[i].emails, rNodes[j].emails);
}
}
}
The code snippet you provided is not completed or buggy,
(like unused sNodes, item, compare...and I can't find where is i)
and what you want to do is also unclear for me.
But let me suppose you want to do compare, if not match, do some copy.
Then you should break the for strcmp loop when you find unmatch node,
so you can copy target node, not just set flag.
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.)