I was solving a problem which allowed two types of operations: subtracting one from a number or multiplying it by two, with the source and the destination numbers provided. Input constraints are 1<=n<=10^4 for both numbers. I'm supposed to output the number of operations needed to produce the desired number from the given one. The following is my implementation, getting runtime error and, obviously, I do not know why. It'll be awesome if someone explains the bug. Thanks.
#include <stdio.h>
#include <stdlib.h>
int g[22222][3], v[2222], size;//g == graph, v == visited and size == the size of queue
typedef struct _queue
{
int val;
struct _queue *next;
struct _queue *prev;
} queue;
queue *head=NULL, *last=NULL;
void push(int val)
{
queue *ptr=(queue *) malloc(sizeof(queue));
ptr->next=NULL;
ptr->val=val;
if (head)
{
last->next=ptr;
ptr->prev=last;
}
else
{
head=ptr;
ptr->prev=NULL;
}
last=ptr;
}
void pop()
{
if (size)
{
queue *ptr=last;
last=last->prev;
if (head) last->next=NULL;
free(ptr);
}
}
int front() {return last->val;}
int bfs(int s, int d)//s == source and d == destination
{
int cnt=0;
push(s);
size++;
v[s]=1;
while (size)
{
int u=front();
pop();
size--;
for (int j=1; j<=2; j++)
{
if (d==g[u][j]) return (cnt+1);
if (!v[g[u][j]])
{
v[g[u][j]]=1;
size++;
push(g[u][j]);
}
}
cnt++;
}
}
int main()
{
int n, m, val;
scanf("%d%d", &n, &m);
if (n==m) {printf("0"); return 0;}
val=(n>m?n:m)*2;
v[0]=1;
for (int i=1; i<=val; i++)
{
g[i][1]=2*i;
g[i][2]=i-1;
}
printf("%d", bfs(n, m));
return 0;
}
You have implemented a stack i.e. LIFO (last in first out): you are adding to the end and retrieving from the end.
You should implement a queue i.e. FIFO (first in first out), so if you add to end, you should retrieve from front:
void pop()
{
if (size)
{
queue *ptr=head;
head=head->next;
if (head) head->prev=NULL;
free(ptr);
}
}
int front()
{
return head->val;
}
Also, I guess your aim is to count the smallest number of operations required to produce the desired number from a given one. Your cnt variable does not represent the smallest number of operations, it represents the number of times you retrieved an element from the queue. You need to increment it for each new level instead.
Finally, your bfs should return a value even if there is no path from s to d, so you should put return 0; after the while(size){} loop.
UPD. You need to skip g[u][j] if it is larger than 2 * (10^4) inside of bfs, otherwise those values be enqueued which is a waste of space. By the way your v array has only 2222 elements, it should have at least 20001 (v[20000] is the last one)
Related
I am implementing BFS in C language using adjacency matrix. I am using queues(linked list) to perform the enqueue and dequeue operations.
My code is dequeuing the first vertex,i.e. 1 but after than the adjacent vertices to 1, i.e 2 & 3 are getting enqueued but not getting dequeued due to which my display is one giving 1 2 3 as output and not the rest of the vertices which are not adjacent to 1.
The graph for which I am doing BFS is shown and its adjacency matrix has been created in the main function.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
}*front=NULL,*rear=NULL;
void enqueue(int x)
{
struct node *t; //temporary node for addition of new node
t=(struct node*)malloc(sizeof(struct node));
if(t==NULL) //Heap is full
printf("Queue is full\n");
else
{
t->data=x;
t->next=NULL;
if(front==NULL && rear==NULL) //queue is empty
front=rear=t; //only one element in linked list
else
{
rear->next=t;
rear=t;
}
}
//printf("Vertex enqueued %d \n",t->data);
//printf("Rear pointing at %d \n",rear->data);
}
int dequeue()
{
int x=-1;
struct node *t;
if(front==NULL && rear==NULL)
printf("Queue is empty\n");
else
{
t=front;
front=front->next;
x=t->data;
free(t);
}
//printf("Vertex dequeued %d \n",x);
//printf("Front pointing at %d \n",front->data);
return x;
}
int isEmpty()
{
if(front==NULL)
return 1;
else
return 0;
}
void BFS(int G[][7],int start,int n) //n-dimension
{
int i=start; //starting index
int visited[7]={0};
printf("%d ",i);
visited[i]=1;
enqueue(i);
while(!isEmpty())
{
i=dequeue(); //control is not going back here after dequeueing 1. 2 & 3 getting enqueued but are not getting dequeued.
for(int j=1;j<=n;j++)
{
if(G[i][j]==1 && visited[j]==0)
{
printf("%d ",j);
visited[j]=1;
enqueue(j);
}
}
}
}
int main()
{
int G[7][7]={{0,0,0,0,0,0,0},
{0,0,1,1,0,0,0},
{0,1,0,0,1,0,0},
{0,1,0,0,1,0,0},
{0,0,1,1,0,1,1},
{0,0,0,0,1,0,0},
{0,0,0,0,1,0,0}};
BFS(G,1,7);
return 0;
}
How I debugged it:
Add a static int counter to the outer scope.
Increment the counter when you put an item on the q.
Decrement the counter when you remove an item from the q.
Verify, in dequeue, that (front == NULL) == (counter == 0) -- these conditions must be the same. Report an error otherwise. man 3 assert for a tidier way to do this.
In isEmpty(), also verify the same condition.
It immediately noted that front was 0 while count was 2.
In dequeue, you check the condition:
if(front==NULL && rear==NULL)
yet when you remove a node, you never update rear. Changing the popping of front to:
if ((front=front->next) == NULL) {
rear = NULL;
}
seems to fix it right up for you. Note, you bothered to write an "isEmpty()", why not use it in enqueue & dequeue? The following:
if (isEmpty()) {
front = rear = t;
}
is much better documented than:
if (front==NULL && rear == NULL) // queue is empty
front = rear = t;
I'm a bit stuck on how to make a user defined function that would printout the output. I also have to make a user defined function that will add up the data in each node and print out the total but it's not adding up correctly and the format is a little off as well.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char printout();
int sum();
typedef struct node
{
int number;
struct node*next;
} node;
char printout()
{
};
int sum()
{
int s,sum_all=0, node_sum=0;
for(s=0;s=100;s++)
{
sum_all=node_sum+s;
return printf("The sum of all nodes is %d.\n",sum_all);
};
};
int main()
{
srand (time(NULL));
int i, total=0;
struct node*head=malloc(sizeof(struct node));
head->number = rand()%100;
printf("Node #%d contains %d.\n", 0, head->number);
struct node*here=head;
for (i=1; i<100; i++)
{
here->next=malloc(sizeof(struct node));
here->number=rand()%100;
printf("Node #%d contains %d.\n", i, here->number);
};
total=sum(here->number);
printf("%2.2d", total);
return 0;
}
There is the litany of errors here, but let's just focus on the most important meat:
You should be pass the list's head to the function sum(), ie
sum(head); // This is how you call most linked list functions.
by which you should change the header to
int sum(struct node *head)
{ ... }
This is not an array. You should traverse the linked list correctly.
I can't show all the code for you, as this is what your professor wants you to learn.
But you should be using these
for( struct node*p = head; p!=NULL; p=p->next)
instead of these
for( s=0; s<=100; s++)
You also forgot to step forward in your malloc-and-fill-with-rand loop
here = here->next; // this does in linked lists what i++ does in arrays
and this
sum_all += p->number; // p->number is analogous to array[i]
instead of
sum_all = node_sum +s; // what are s and node_sum anyway?
Also, if you insist that sum return something,
It should return, well, the sum;
return sum_all;
And don't print it inside the function
printf("The sum of all nodes is %d.\n",sum_all); // please don't
Because you're already printing it outside.
total = sum(head);
printf("%2.2d", total);
Please try to think first what your code is going to accomplish instead of putting code blankly.
It will help you a lot. Good luck!
I have to make a function which counts how many elements my tree have. My tree is not binary, is the most general kind of tree.
The node is:
typedef struct node{
char item;
int number_of_sons;
node **sons;
}
My counting function is this
void numbering(node *HT,int ok=0)
{
static int number = 0;
if (ok == 1)
{
printf("%d", number);
return;
}
if (HT == NULL)
{
return;
}
else
{
number++;
for (int i = 0;i < HT->nr_of_sons;i++)
{
numbering(HT->next[i], 0);
}
}
}
Is there a way to improve this function to make this faster?
EDIT: the way I use this function is:
int main()
{
//create tree;
numbering(tree,0);
numbering(tree,1);
}
When I call the function the second time it prints my result
You have a very strange recursive function there--you're using a static variable in the function which is never reset, so the function can only be used once per program run!
I'd rewrite it this way:
size_t nodecount(node *root)
{
size_t count = 0;
if (root)
{
count++;
for (int i = 0; i < root->nr_of_sons; i++)
{
count += nodecount(root->sons[i]);
}
}
return count;
}
If you really want to speed things up, you could augment your node structure by adding a size_t subtree_count field which you'd maintain whenever you insert or remove nodes. Another idea is to compact the pointer-to-array-of-sons into the node structure directly:
typedef struct node{
char item;
int number_of_sons;
node_t *sons[0];
} node_t;
What I've done here is made it so the sons variable is an array rather than a pointer to an array. But it has size zero (n.b. use [] or [1] if your compiler requires), because you don't know the number of sons at compile time. But you can simply allocate nodes with the right amount of space:
node_t* tree = (node_t*)malloc(sizeof(node_t) + num_sons*sizeof(node_t*));
This reduces pointer indirection by one layer, which may help performance.
Maybe this is better and more efficient:
int numbering(node *HT)
{
if (!HT)
{
return 0;
}
int num = 1;
for (int i = 0;i < HT->nr_of_sons;i++)
{
num += numbering(HT->next[i]);
}
return num;
}
I deleted your ok variable and changed the returned value from void to int.
In the case base you return 0;
For the leaf so they will return 1;
For inner nodes they will return 1 + the numbers of nodes in the
subtree.
I am trying to implement a generic circular buffer (queue) in C. Here is my code so far:
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>
CIRCLEQ_HEAD(circleq, entry) head;
struct circleq *headp; /* Circular queue head. */
struct entry {
CIRCLEQ_ENTRY(entry) entries; /* Circular queue. */
int number;
};
int main()
{
CIRCLEQ_INIT(&head);
// Add some numbers to the queue
int i;
for (i = 0; i < 10; i++) {
struct entry* n = malloc(sizeof(struct entry));
n->number = i;
CIRCLEQ_INSERT_HEAD(&head, n, entries);
printf("Added %d to the queue\n", n->number);
}
// Remove a number from the queue
struct entry *n;
n = CIRCLEQ_FIRST(&head);
CIRCLEQ_REMOVE(&head, head.cqh_first, entries);
printf("Removed %d from the queue\n", n->number);
return 0;
}
Which produces the following output:
Added 0 to the queue
Added 1 to the queue
Added 2 to the queue
Added 3 to the queue
Added 4 to the queue
Added 5 to the queue
Added 6 to the queue
Added 7 to the queue
Added 8 to the queue
Added 9 to the queue
Removed 9 from the queue
I am not very experienced with C, and my questions are:
How can I set a limit on the queue, so, for example, only 5 numbers
can fit into the buffer at a time? If another item is attempted to
be added after this, I should be able to detect it and do something
about it (ignore it, wait, exit program, etc.).
It seems my code removed the last item from the buffer - how can I
make it remove items from the tail (number 0 instead of 9, in my
example)?
I've read through http://linux.die.net/man/3/queue, but it doesn't seem clear how I can accomplish the above two things.
If you look at the description of circular-buffer, one of the main benefits of this kind of buffer is that it uses a single fixed allocation, whereas yours is basically just a circularly linked list. The fixed size used at creation specifies the limit of the number of elements the ring buffer can hold.
If you have a properly implemented circular buffer, removing an item involves simply advancing the tail pointer, wrapping back to the front if necessary.
An example struct representing a circular buffer might look like the following:
struct circleq
{
int* buf;
int head;
int tail;
int size;
};
void init(struct circleq* q, int size)
{
q->buf = malloc(sizeof(int) * size);
q->head = 0;
q->tail = size - 1;
q->size = size;
}
void insert(struct circleq* q, int val)
{
if(q->head == q->tail) { } // queue full, error
else
{
q->buf[q->head] = val;
q->head = (q->head + 1) % q->size;
}
}
int remove(struct circleq* q)
{
if((q->tail + 1) % q->size == q->head) { return 0; } // queue empty, error
else
{
int val = q->buf[q->tail];
q->tail = (q->tail + 1) % q->size;
return val;
}
}
void destroy(struct circleq* q)
{
free(q->buf);
}
I created a program to sort double linked list in ascending order, and the result was unexpected, but when I used the same program for descending order by changing a line in it, it worked perfectly. Please tell where m going wrong
/*Structure of double linked list */
struct dlink
{
int num;
struct dlink *plink; //previous address
struct dlink *nlink; //next address
};
void main()
{
clrscr();
struct dlink *st;
st=NULL;
append(&st,100); //to put values in double linked list
append(&st,32);
append(&st,200);
append(&st,107);
display(st);
ascending(&st);
display(st);
getch();
}
/* function to add values to double linked list */
void append(struct dlink **q,int n)
{
struct dlink *temp,*r;
temp=*q;
if(temp==NULL)
{
temp=(dlink *)malloc(sizeof(dlink));
temp->num=n;
temp->plink=NULL;
temp->nlink=NULL;
*q=temp;
}
else
{
while(temp->nlink!=NULL)
temp=temp->nlink;
r=(dlink *)malloc(sizeof(dlink));
r->num=n;
r->nlink=NULL;
r->plink=temp;
temp->nlink=r;
}
}
void ascending(struct dlink **q)
{
struct dlink *temp,*s,*p=NULL;
temp=*q;
int a=count(*q);
printf(" a %d ",a);
for(int i=0;i<a;i++,temp=temp->nlink)
{
s=temp->nlink;
for(int j=i+1;j<=a;j++,s=s->nlink)
{
if((temp->num) < (s->num)) //for ascending i was using //if(temp->num > s->num but it is not getting desired result it is just printing //one value and by this one for descending order program is working perfectly //for descending order
{
(s->plink)->nlink=s->nlink;
if(s->nlink!=NULL)
(s->nlink)->plink=s->plink;
s->plink=temp->plink;
s->nlink=temp;
temp=s;
(temp->nlink)->plink=temp;
}
}
if(i==0)
*q=temp;
if(i!=0)
{
p->nlink=temp;
temp->plink=p;
}
p=temp;
}
temp=*q;
/* To see if the addresse , previous address , next address are correct */
while(temp!=NULL)
{
printf("as %u %u %u\n",temp->plink,temp->nlink,temp);
temp=temp->nlink;
}
}
Look at this part
int a=count(*q);
for(int i=0; i<a; i++,temp=temp->nlink)
{
s=temp->nlink;
for(int j=i+1; j<=a; j++,s=s->nlink)
{ ....
Seems you are using indexes from 0 (first loop) to count(*q) (second) for a list with count(*g) elements.
Something is probably wrong in your algorithm - even if it doesnt cause "index out of bounds" errors (because you don't use arrays).
And it appears when you try to sort the second way, because you have not tested the first way seriously enough.