I've writen a Bread-First Search algorithm in C that searches through a graph structure (in this case representing a grid of streets) and returns ALL possible routes from node A to node B.
What I've found is that the function works very quickly for small graphs (around 24 nodes), but will crash with anything larger than this. I thought it was a problem with too many mallocs, so I added free() into my function to remove space while running through the queue. This does not, unfortunately, fix the problem. Also note that I never get the error message "Out of memory," either, so I'm not sure what's happening...
void BFS_search(struct map *m, int start, int end){
int n = m->nb_vertice+1;
int i=0;
int num=0;
//BFS requires a queue (pile) to maintain a list of nodes to visit
struct queue {
int current_node;
int visited[n]; //cannot be a pointer! Otherwise the pointer may influence other queue structures
struct queue *suivant;
};
//Function to add a node at the end of the queue.
void addqueue (int value, struct queue *old, int * old_seen) {
int i;
if (old->suivant==NULL){
struct queue *nouveau;
nouveau = (struct queue *)malloc(sizeof(struct queue));
if (nouveau == NULL){
printf("\n\nSnap! Out of memory, exiting...\n");
exit(1);
}
nouveau->current_node = value;
for (i = 0; i <= n; ++i){
if (old_seen[i]==1)
nouveau->visited[i]=1;
else nouveau->visited[i]=0;
}
nouveau->suivant = NULL;
old->suivant=nouveau;
return;
}
else addqueue(value,old->suivant,old_seen);
}
struct queue * dequeue (struct queue *old){
struct queue *nouveau;
nouveau = (struct queue *)malloc(sizeof(struct queue));
if (nouveau == NULL){
printf("\n\nSnap! Out of memory, exiting...\n");
exit(1);
}
nouveau = old->suivant;
free(old);
return(nouveau);
}
//the actual Breadth First Search Algorithm
int BFS(struct map *m, struct queue *q, int num, int end){
int k;
q->visited[q->current_node]=1; //mark current node as visited
while(q!=NULL){
//if we reached the destination, add +1 to the counter
if (q->current_node==end){
num+=1;
}
//if not the destination, look at adjacent nodes
else {
for (k=1;k<n;++k)
if (m->dist[q->current_node][k]!=0 && q->visited[k]!=1){
addqueue(k,q,q->visited);
}
}
//if queue is empty, stop and return the number
if (q->suivant==NULL){
return(num);
}
//if queue is not empty, then move to next in queue
else
return(BFS(m,dequeue(q),num,end));
}
}
//create and initialize start structure
struct queue *debut;
debut = (struct queue *)malloc(sizeof(struct queue));
for (i = 0; i <= n; ++i)
debut->visited[i]=0;
debut->current_node=start;
debut->visited[start]=1;
debut->suivant = NULL;
num=BFS(m,debut,0,end);
printf("\nIl existe %d routes possibles! \n",num);
}
Note that I'm using a struct map, which stores all the edges and nodes for my graph, including nb_vertices (number of nodes), and a distance matrix dist[i][j], which is the distance from node i to j, or 0 if not connected.
Any help would be greatly appreciated! I assume it's an error with the amount of memory available. I'd at least like to have a way to output a specific error message if I can't avoid the memory problems...
Your dequeue operation is leaking memory. You malloc some memory and store the pointer in nouveau, but then you say nouveau = old->suivant, losing the malloc'd buffer. There's no need to malloc at all when popping from the front of a linked list:
struct queue *dequeue(struct queue *q)
{
struct queue *next = q->suivant;
free(q);
return next;
}
As for why you don't get an "out of memory" error, I'm guessing you're on Linux and you're experiencing the sad effects of overcommit.
Related
#include <stdio.h>
#include <stdlib.h>
struct queue
{
int front;
int rear;
int size;
int *arr;
};
void enqueue(struct queue *q, int value)
{
if(q->rear!=q->size-1)
{
printf("Entry\n");
q->rear++;
q->arr[q->rear] = value;
}
}
int main()
{
struct queue *q; /*struct queue *q=(struct queue *)malloc(sizeof(struct queue));*/
q->front = -1;
q->rear = -1;
q->size = 10;
q->arr = (int *)malloc((q->size) * sizeof(int));
enqueue(q,14);
enqueue(q,7);
enqueue(q,5);
enqueue(q,4);
enqueue(q,3);
enqueue(q,2);
for(int i=0;i<q->rear;i++){
printf("%d ",q->arr[i]);
}
return 0;
}
I was expecting the elements of the queue to be printed.
When the line
"struct queue *q;"
is replaced with this "
*struct queue *q=(struct queue *)malloc(sizeof(struct queue));"
it works, what is the reason?
The segmentation-fault occurs because you have not allocated memory for q.
What you have written as:
struct queue *q;
Is a pointer, that is, a variable that stores the memory address of another variable. You have created something that can point to memory but have not provided it any memory to point to.
malloc provides you memory from the heap, which is a typical way of having memory allocated and is why the commented code works.
An alternative would be to use memory on the stack:
struct queue q;
q.front = -1;
q.rear = -1;
q.size = 10;
q.arr = (int *)malloc((q.size) * sizeof(int));
And then using it as:
enqueue(&q,14);
struct queue *q;
q = (struct queue *)malloc(sizeof(struct queue)); /*In order to write data, you first need to allocated to memory for it. and if you do it like q->arr you will allocated to memory for the second step so (think of this list as an array if you do q->arr you will allocated for arr[1] instead of arr[0])*/
q->front = -1;
q->rear = -1;
q->size = 10;
/but this will only allocate the first part in memory (only for arr[0])/
/*so you can write code in void enqueue(struct queue *q, int value) to allocated a new memory in each operation */
/I understand that you are trying to determine the memory in one go by assigning size to 10 , but you can not do like this.because the part you allocate here is just a value you put in arr[0], you can't use it as the size of your list./
I am given these structure declarations in order to implement a queue collection that uses a circular linked list.
typedef struct intnode {
int value;
struct intnode *next;
} intnode_t;
typedef struct {
intnode_t *rear; // Points to the node at the tail of the
// queue's linked list
int size; // The # of nodes in the queue's linked list
} intqueue_t;
intnode_t *intnode_construct(int value, intnode_t *next)
{
intnode_t *p = malloc(sizeof(intnode_t));
assert (p != NULL);
p->value = value;
p->next = next;
return p;
}
/* Return a pointer to a new, empty queue.
* Terminate (via assert) if memory for the queue cannot be allocated.
*/
intqueue_t *intqueue_construct(void)
{
intqueue_t *queue = malloc(sizeof(intqueue_t));
assert(queue != NULL);
queue->rear = NULL;
queue->size = 0;
return queue;
}
I'm trying to create a function that will enqueue at a specified value (append it to the rear of the queue), and I need to consider the two cases in which the queue is empty and when the queue has one or more elements. This is the code I have so far:
void intqueue_enqueue(intqueue_t *queue, int value)
{
intnode_t *p = intnode_construct(value, NULL);
if(queue->rear->next == NULL) {
//the queue is empty
queue->rear->next =p;
} else {
//the queue is not empty
queue->rear=p;
}
queue->rear=p;
queue->size++;
}
This code gives me a runtime error so I'm not sure whats wrong. In the code, I'm assuming queue->rear->next is the front, however I think this is where the problem might be. All help is greatly appreciated. Thanks!
Your problem occurs on this line:
if(queue->rear->next == NULL) {
The first time you call the function, queue->rear is NULL. Thus when you try to dereference it to get queue->rear->next you get the runtime error.
To fix this code, update intqueue_enqueue to just check if queue->size==0, and if so then you need to initialize it by setting queue->rear=p and p->next=p. Then update the else clause so that it inserts the element between the two existing elements. Hint: you'll need to store queue->rear->next in p.
Edit
To address your comment, here's how to graphically think about a list with three elements:
<element1: next==element2> <element2: next==element3> <element3: next==element1>
And queue->rear points to element3. So, to insert a fourth element, you need to make it so that queue->rear points to element4 and element4->rear needs to point to element1. Remember that the location of element is stored in rear->next.
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'm trying to implement a queue in c. I have gotten as far as implementing an enqueue function in my code. However, when I am testing it I don't get the desired output. Can someone please tell me what I am doing wrong?
struct queue{
int array[30];
int *front; //pointer to front of queue
int *rear; //pointer to rear of queue
int count; //counts number of elements in queue
};
//initialising a queue
struct queue * new_Queue()
{
struct queue *q;
q->count=0;
q->front=&q->array[-1];
q->rear=&q->array[-1];
return q;
};
int queueCount(struct queue *q)
{
return q->count;
}
int isFull(struct queue *q)
{
if(q->count==30){
printf("%s","Buffer is full!");
return 1;
}
return 0;
}
int isEmpty(struct queue *q)
{
if(q->count==0){
printf("%s","Queue is empty!");
return 1;
}
return 0;
}
int enqueue(struct queue * q,int i)
{
if(isFull(q)){
return 0;
}
if(isEmpty(q)){
q->front+1;
}
int k=*(q->rear+1);
q->array[k]=i;
printf("enque success!");
return 1;
}
int main(int argc, char**argv)
{
int i=10;
struct queue *newQueue;
enqueue(newQueue,i);
int j= queueCount(newQueue);
printf("%d",j);
}
You need memory for your queue. At the moment, you have an uninitialised pointer that points to a random location in memory. Dereferencing that pointer is undefined behaviour and will very likely give you a seg fault.
You have to decide how you want to store your queue. You can either allocate it on the heap with malloc. This is what your function new_Queue should do:
struct queue *new_Queue()
{
struct queue *q = malloc(sizeof(*q)); // TO DO: Error checking
q->count = 0;
q->front = q->array;
q->rear = q->array;
return q;
}
You client code then looks like this:
struct *q = new_Queue();
enqueue(q, x);
// Do more stuff ...
free(q); // Release resources
The queue structure isn't big. You can also allocate it on the stack. In that casen you need an initialisation function :
void queue_init(struct queue *q)
{
q->count = 0;
q->front = q->array;
q->rear = q->array;
}
and call it like:
struct queue *q;
queue_init(&q);
enqueue(&q, 12);
Note the addres-of operator &. You don't have to (and cannot) free the queue here.
You can't access the array at index -1. You could make the front the next element to dequeue and the rear point to the space where the next element is enqueued. In a circular buffer, that will make the cases of empty and full list indistiguishable, but you can use the count to distinguish between them.
I want to create a circular queue using linked list,also i want to create instance of that data structure(queue) not just one queue, many queues without repeating the code. this is what i came up with...
#include <stdio.h>
#include <stdlib.h>
struct queue
{
int info;
struct queue *next;
struct queue *front;
struct queue *rear;
};
void create(struct queue **q)
{
(*q)->next = 0;
(*q)->front = 0;
(*q)->rear = 0;
}
struct queue* makenode(int item){
struct queue* p = (struct queue*)malloc(sizeof (struct queue));
if (p) p->info = item;
return p;
}
void addLast(struct queue **q, int item){
struct queue* p = makenode(item);
if ((*q)->front == NULL){
(*q)->front = (*q)->rear = p;
(*q)->front->next = (*q)->front;
(*q)->rear->next = (*q)->rear;
}
else
{
(*q)->rear->next = p;
p->next = (*q)->front;
(*q)->rear = p;
}
}
int delFirst(struct queue **q){
struct queue *p = (*q)->front;
if ((*q)->front == 0)
printf("\nEmpty Queue\n");
else
{
int temp = (*q)->front->info;
if (((*q)->front->next) != ((*q)->front))
{
(*q)->front = (*q)->front->next;
(*q)->rear->next = (*q)->front;
}
else
{
(*q)->front = 0;
}
return temp;
}
free(p);
}
void main()
{
struct queue *premium, *normal;
create(&premium);
create(&normal);
addLast(&premium, 5);
addLast(&premium, 10);
addLast(&normal, 20);
addLast(&normal, 30);
printf("%i\n", delFirst(&premium));
printf("%i\n", delFirst(&premium));
delFirst(&premium);
printf("%i\n", delFirst(&normal));
printf("%i\n", delFirst(&normal));
delFirst(&normal);
getch();
}
Is there any good way to do this? I kinda feel my code is complicated. I am new to C programming and I only learned basics about queues and linked list.so i don't know even my code is 100% right or an elegant code. I compiled this code using DevC++ works fine, but when I compile it using MS Visual Studio 2013, it gave me an exception "Access violation writing location....”. so i am very sure my code is not that good. Please help me out. Thanks
Problem 1: data structure
You have one structure that contains both the linked list item (info and next element) and the queue structure (front and rear, which should be the same for all elements.
I'd suggest to use:
struct queue_item
{
int info;
struct queue_item *next;
};
struct queue
{
struct queue_item *front;
struct queue_item *rear;
};
Problem 2: queue creation
When you call create(), the pointer which address you pass (for example premium) is not yet initialized. It can point anywhere ! Most certainly to an invalid location. It doesn't point to a queue yet. So when you do things like (*q)->next = 0;, you try to overwrite an illegal location.
With the data structure proposed above, I propose the following :
struct queue* create (struct queue *q) /* q points to a queue already allocated, or it is NULL */
{
if (q==NULL)
q = malloc(sizeof (struct queue));
if (q) {
q->front = 0;
q->rear = 0;
}
return q;
}
In main() you'd then have the choice:
struct queue *premium, normal;
premium = create(NULL); /* allocate the queue structure */
create(&normal); /* use an allocated structure */
Problem 3: Node pointers not initialized at node creation
malloc() does not initialize the memory it returns. If you do'nt initialize the link pointer(s), these may in fact contain something else than NULL.
struct queue_item* makenode(int item){
struct queue* p = (struct queue_item*)malloc(sizeof (struct queue_item));
if (p) {
p->info = item;
p->next = NULL; /* There is no link yet, so make it clear to avoid any surprises later. */
}
return p;
}
Problem 4: Inconsistencies when adding/deleting items
With the new data structure, you'll have to adapt your addLast() and delFirst(). But it'll be clearer, because front and rear are at the level of the queue, and next is only at the level of the item.
From the signature, it'll be posible to avoid double indirection because the pointer to the queue will never be changed by these operations:
void addLast(struct queue *q, int item);
int delFirst(struct queue *q);
Your first problem is that you invoke create() on uninitialized pointers:
void create(struct queue **q)
{
(*q)->next = 0;
…
}
int main()
{
struct queue *premium, *normal;
create(&premium);
create(&normal);
Either you need to call makenode() inside the create() function or in main(), or you need to provide structures for premium and normal to point at.
Option A:
void create(struct queue **q)
{
*q = makenode(0);
if (*q != 0)
{
(*q)->next = 0;
…
}
}
Option B:
int main()
{
struct queue q_premium, q_normal;
struct queue *premium = &q_premium;
struct queue *normal = &q_normal;
create(&premium);
create(&normal);
Either technique can be made to work, but Option B requires care because the structures q_premium and q_normal are not allocated (though they could be if that was necessary). However, the signature of create() suggests that Option A is what was intended because Option B really doesn't require the double pointer in create().
I'm not clear what, if any, benefit the mix of three pointers — front, rear, next — provides to your structure. I implemented a circular DLL for my own benefit, just to see what might be involved, and I only needed a data pointer and next and previous pointers. From any element in the list, you can reach every other element in the list. You can insert before or after a given node, remove a given node, apply a function to all nodes, or find the first node that matches a predicate provided by a function (and get the next node, previous node or the data), or destroy the entire list.
My impression is that your code would be simpler without one of the pointers.
With the Option A change, the code compiles and seems to work, producing:
5
10
Empty Queue
20
30
Empty Queue