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.
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 need to reverse a stack using queue. The reverseStack() function only uses push()and pop()when adding or removing integers from the stack, and only uses enqueue() and dequeue() when adding or removing integers from the queue.
But I got a segmentation fault at push(&s, dequeue(&q));.
Could anyone tell me what does this mean? Thanks.
Here is my code:
void reverseStack(Stack *s)
{
Queue *q;
while(!isEmptyStack(s)) //pop items from stack and queue into q
{
enqueue(&q, pop(s));
}
while(!isEmptyQueue(q)) //dequeue items from queue and push to stack
{
push(&s, dequeue(&q));
}
}
Updated:
typedef struct _listnode{
int item;
struct _listnode *next;
} ListNode;
typedef struct _linkedlist{
int size;
ListNode *head;
ListNode *tail;
} LinkedList;
////////////////////////////////// stack ///////////////////////////////////////////////////////
typedef struct stack{
LinkedList ll;
} Stack;
//////////////////////////////////// queue ////////////////////////////////////////////////////////
typedef struct _queue{
LinkedList ll;
} Queue;
I was given these list of functions and I need to create the reverseStack() function based on these.
void push(Stack *s, int item){
insertNode(&(s->ll), 0, item);
}
int pop(Stack *s){
int item;
if(!isEmptyStack(s)){
item = ((s->ll).head)->item;
removeNode(&(s->ll), 0);
return item;
}
return INT_MIN;
}
int peek(Stack *s){
return ((s->ll).head)->item;
}
int isEmptyStack(Stack *s){
if ((s->ll).size == 0)
return 1;
return 0;
}
void enqueue(Queue *q, int item){
insertNode(&(q->ll), q->ll.size, item);
}
int dequeue(Queue *q){
int item;
item = ((q->ll).head)->item;
removeNode(&(q->ll), 0);
return item;
}
int isEmptyQueue(Queue *q){
if ((q->ll).size == 0)
return 1;
return 0;
}
There are several problems here.
Your reverseStack method is:
void reverseStack(Stack *s)
{
Queue *q;
while(!isEmptyStack(s)) //pop items from stack and queue into q
{
enqueue(&q, pop(s));
}
while(!isEmptyQueue(q)) //dequeue items from queue and push to stack
{
push(&s, dequeue(&q));
}
}
Here, you declare q, but you never define it. The first thing you need to do is make q point to something, or perhaps you meant to write:
Queue q;
Which would allocate space for a Queue structure on the processor stack.
With the code as written, I don't understand how it works. The calls to enqueue should die because q is never assigned a value. Although I guess it's possible, C being the friendly language it is, that since you're passing the address of q rather than the value of q, you're just corrupting the call stack.
In any event, unless you fix that (either make q a non-pointer, or assign it a value by calling malloc), you're going to have problems. If it really is supposed to be dynamically allocated, then replace &q with q in that function.
Your push is defined as:
void push(Stack *s, int item){
insertNode(&(s->ll), 0, item);
}
That says you need to pass a Stack * (pointer to a stack) as the first parameter.
But in your reverseStack function, s is already a Stack * (pointer to a stack). But you're calling push with the address of the pointer. You're passing a Stack ** (pointer-to-pointer to stack).
The correct call would be:
push(s, dequeue(q)); // or maybe dequeue(&q), depending on how you
// you end up defining q.
Your C compiler should have given you errors on those lines. Or ... well, C being what it is, perhaps it just gave you warnings.
A compiler warning is nothing more than an error in disguise. Compile with the highest possible warning level, enable the "warnings as errors" option, and fix every warning.
I have the following code in C, trying to develop an Operating System simulation:
Queue.c:
typedef enum {running,readyproc,waiting,suspended}status;
typedef struct pcb {
long pid;
char* pname;
long priority;
long sleepperiod;
long* context;
status stat;
}PCB;
typedef enum {ready, timer, suspend} queuetype;
typedef struct {
int size;
int capacity;
PCB ** data;
queuetype qt;
}Queue;
void queue_init(Queue *q, queuetype qt){
q->size =0;
q->capacity = QUEUE_INITIAL_CAPACITY ;//100
q->data = (PCB **)calloc(q->capacity,sizeof(PCB*));
q->qt = qt;
}
PCB* queue_pop (Queue* q){
PCB* toReturn;
int i;
toReturn = q->data[0];
for (i=0;i<q->size;i++){
q->data[i]=q->data [i+1];
}
free(q->data[q->size]);
q->size--;
printf ("toReturn id:%ld pname: %s\n", toReturn->pid, toReturn->pname);
return toReturn;
}
Knowing that the queue gets initialized and filled with PCBs. I do always get a segafault on calling:
PCB* pcb = queue_pop(&queue);
EDIT:
Here is the function that would fill the queue:
void queue_append(Queue *q, PCB* value)
{
q->data[q->size++] = value;
}
EDIT2:
the printf before the return in queue_pop returns this:
toReturn id: 2 pname: test1c_a
which corresponds to what I want to pop from that queue.
for (i=0;i<q->size;i++){
q->data[i]=q->data [i+1];
}
If q->size == q->capacity, then you'll run off the end of q->data (it will access q->data[q->capacity], which is one past its allocation length).
P.S. There are much more efficient ways to do this.
Below seems to be a problem.
free(q->data[q->size]);
lets say two elements are in Queue q->size = 2 hold by
q->data[0] and q->data[1]
so when queue_pop called. Above code will free q->data[2]. This may leads to seg-fault.
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
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.