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
Related
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.
void insert_queue (queue *this, queue_item_t item) {
//Inserts a new item at the end of queue.
queue_node *temp = malloc(sizeof (struct queue_node));
temp->item = item;
if (isempty_queue(this)) this->front = temp;
else this->rear->link = temp;
this->rear = temp;
//free(temp);
}
queue_item_t remove_queue (queue *this) {
assert (! isempty_queue (this));
//This removes the first item from queue.
queue_item_t temp = this->front->item;
this->front = this->front->link;
return temp;
}
I'm getting a seg fault error when I try to free 'temp'. I'm supposed to free a node after using it, right? So, how would I prevent memory leak in this situation? Any ideas?
Thanks.
When I remove free(temp), everything works fine, but I'm getting memory leaks. I'm not sure where to put free if it doesn't belong in this function. I also added my remove function. Should free go in here?
EDIT EDIT: Thank you everyone, here is my updated code.
queue_item_t remove_queue (queue *this) {
assert (! isempty_queue (this));
queue_node *temp = this->front;
queue_item_t rVal = temp->item;
//Moves on to the next one.
this->front = this->front->link;
//Free the unlinked node.
//free(temp->item); <<<<---- This causes program to fail.
free(temp);
return rVal;
}
Memory leaks are still occurring.
You are not done using the node when insert_queue finishes. The insert_queue routine uses temp to hold a pointer to the node, and insert_queue is done using temp when it returns, but the node itself is part of the linked list, so it is in use.
You finish using the node when remove_queue removes it from the list. remove_queue should pass the pointer to the node to free to release its memory.
Do not think of temp as a node. It is only an object that temporarily holds a pointer to the node. The node itself is a separate thing.
Well, if you're creating and inserting a new queue, why would you want to delete it? Remember, when you use malloc() you're reserving some data independent of the block you are in. Free() is what you use to destroy this memory created with malloc(). All locally scoped (NOT created with malloc) data/variables will automatically be destroyed at the end of they're respected blocks. Data created with malloc() will (in most cases) not.
void insert_queue (queue *this, queue_item_t item)
{
//Inserts a new item at the end of queue.
queue_node *temp = malloc(sizeof (struct queue_node));
temp->item = item;
if (isempty_queue(this))
this->front = temp;
else
this->rear->link = temp;
this->rear = temp;
//free(temp); // remember tmp is still referring to
// the node, so you will be erasing the
// node you just put inside the queue.
} // end of code block. Variable *temp will be
// automatically freed from memory, but
// its malloc'd data will not. This is good
// because its data is being used inside our
// queue, until it is removed with remove_queue().
Later on inside your remove function you could delete "temp" (its actually the memory allocated using malloc()) using free. Or you could use free(remove_queue(&myq)), and it will yield the exact same result because we are dealing with pointers.
First of all "this" is shadowning a keyword in c++. You should not use it in a c-context either if you ask me - just to avoid misunderstandings.
Second a queue is something where an item, request, person or something is queued at the end and earlier or later removed from the front when it is time (dequed). You seem to implement this as a linked list what is ok.
Next queue_item_t item is allocated on the stack here as copy from the original value, since I do not see that it is a pointer comming in the momory allocated for it will be deleted on the closing }.
I would not call a variable temp if it actually has meaning like newQueueNode. Meaningful application/class/variable/function names are one of the best ways to comment your code.
At last comment, the choosen return and pass by value without an ok parameter, or you will run into issues when you can not return a copy (see my example for size==0), and there is no way to tell the user of the function that something went wrong (queue is empty, in this case)
Here is my (quickly produced and tested) minimum solution for your problem:
#include <stdlib.h>
#include <stdio.h>
struct queue_item_t
{
int exampleItemData;
};
struct queue_node
{
struct queue_item_t *item;
struct queue_node *next;
};
struct queue
{
struct queue_node *firstItem;
struct queue_node *lastItem;
int size;
};
struct queue* createQueue()
{
struct queue *queuePtr = (struct queue *)malloc(sizeof (struct queue));
queuePtr->firstItem = NULL;
queuePtr->lastItem = NULL;
queuePtr->size = 0;
return queuePtr;
}
void queue(struct queue* queueData, struct queue_item_t itemToQueue)
{
// Create new node
struct queue_node* newNode = (struct queue_node*)malloc(sizeof(struct queue_node));
// Create new item
newNode->item = (struct queue_item_t*)malloc(sizeof(struct queue_item_t));
// Copy the item data from itemToQueue that will be deleted on the end of this function
newNode->item->exampleItemData = itemToQueue.exampleItemData;
// Insert the item into the queue
if(0 == queueData->size)
{
queueData->firstItem = newNode;
queueData->lastItem = newNode;
newNode->next = newNode;
}
else
{
queueData->lastItem->next = newNode;
queueData->lastItem = newNode;
}
queueData->size += 1;
// ! itemToQueue will deleted here we must have a copy of the data in the queue }
}
struct queue_item_t dequeue(struct queue* queueData)
{
struct queue_item_t item;
if (1 > queueData->size)
{
// !!! Serious problem if this happens:
// What will you return, an initialized queue_item_t?
// You can not return a null pointer ...
// Better you write ok to a boolean comming in ass parameter or something
}
else if(1 == queueData->size)
{
item.exampleItemData = queueData->firstItem->item->exampleItemData;
free(queueData->firstItem->item);
free(queueData->firstItem);
queueData->firstItem = NULL;
queueData->lastItem = NULL;
}
else if(2 == queueData->size)
{
item.exampleItemData = queueData->firstItem->item->exampleItemData;
struct queue_node* dequeuedNode = queueData->firstItem;
queueData->firstItem = dequeuedNode->next;
queueData->lastItem = dequeuedNode->next;
free(dequeuedNode->item);
free(dequeuedNode);
}
else if (1 < queueData->size)
{
item.exampleItemData = queueData->firstItem->item->exampleItemData;
struct queue_node* dequeuedNode = queueData->firstItem;
queueData->firstItem = dequeuedNode->next;
free(dequeuedNode->item);
free(dequeuedNode);
}
queueData->size -= 1;
return item;
}
int main() {
struct queue* myQueue = createQueue();
struct queue_item_t item;
item.exampleItemData = 665;
queue(myQueue, item);
item.exampleItemData = 666;
queue(myQueue, item);
item.exampleItemData = 667;
queue(myQueue, item);
for(int i = myQueue->size; i > 0; --i)
{
struct queue_item_t dequeuedItem = dequeue(myQueue);
printf("Dequed ITem data = %i\n", dequeuedItem.exampleItemData);
}
// Now the next shows an undefined state if someone dequeues with size 0 or smaller:
struct queue_item_t dequeuedItem = dequeue(myQueue);
printf("Dequed ITem data = %i\n", dequeuedItem.exampleItemData);
// I recommend using a boolean like mentioned above
return 0;
}
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.
I'm implementing a simple priority queue in C for a kernel and so I can't use any standard libraries. The queue holds a head node and each node points to the next in the queue.
typedef struct node node;
struct node {
node *next;
void *data;
};
typedef struct {
node *head;
int n;
} queue;
As you can see, each node holds it data in a void*. I'm having trouble converting this data to lets say an int when I pop the data off the stack.
//push data
int int_data = 100;
push(q, &int_data);
//...
//pop data
node* popped = pop(q);
int *pop_data = popped->data;
printf("pop data (100): %d\n", *pop_data);
Why can't I get the original value here? I seem to be printing a pointer value. Alternatively, is there a better way to handle this?
== edit (sorry should have included these):
void push(queue *q, void *data)
{
node new;
new.data = data;
node *new_ptr = &new;
if(is_empty(q))
{
q->head = new_ptr;
q->n++;
return;
}
int i;
node *curr = q->head;
for(i=0; i<q->n; i++)
{
curr = curr->next;
}
curr->next = new_ptr;
q->n++;
}
node* pop(queue *q)
{
node *curr = q->head;
q->head = curr->next;
return curr;
}
Is your code all in one function? If not, int int_data is getting popped off the stack (not your queue, the actual stack) which is probably why you are printing garbage; you are storing the address of a local variable.
I would suggest changing void* data to int data. (If you need to, you can store an address in an int and can cast it back to a pointer later.)
int int_data = 100;
push(q, int_data);
node* n = pop(q);
int num = n->data;
After reviewing your code again, you have the same problem when adding a new node. node new falls out of scope at the end of the function, so basically all of your nodes in your queue are pointing to invalid memory.
If the "pop" operation is in a different function:
The problem is likely because you're pushing a local variable into your queue.
When you go to pop, this address is no longer valid (or at least not pointing to an int value), so you're printing something strange. As the data is no longer pointing to your int, it probably looks like a memory address.
You can use the glib GPOINTER_TO_INT macro:
#define GPOINTER_TO_INT(p) ((gint) (glong) (p))
But please, take note with the doc note:
YOU MAY NOT STORE POINTERS IN
INTEGERS. THIS IS NOT PORTABLE IN ANY
WAY SHAPE OR FORM. These macros ONLY
allow storing integers in pointers,
and only preserve 32 bits of the
integer; values outside the range of a
32-bit integer will be mangled.
are you setting data = int_data (i.e. int --> void*) or data = &int_data (i.e. int* --> void *) ? In the former case, you have to write printf("pop data (100): %d\n", pop_data);
I am tasked with making a queue data structure in C, as a linked list. Our lecturer gave us a large amount of code to implement a stack, but we have to adapt it to create a queue. The code our lecturer gave us ends up not compiling and segfaulting at the exact same point as the code I wrote for the queue. I'm very new to structs, malloc and C in general, so there could be something painfully obvious I've overlooked.
Here is the code I am using:
#include <stdio.h>
#include <stdlib.h>
struct node{
int data; //contains the actual data
struct node *prev; //pointer to previous node (Closer to front)
struct node *next; //pointer to next node (Closer to back)
};
typedef struct node *Nodepointer;
struct queue{
Nodepointer front;
Nodepointer back;
};
typedef struct queue *Queuepointer;
main(){
Queuepointer myqueue; //create a queue called myqueue
init(myqueue); //initialise the queue
Nodepointer new = (Nodepointer)malloc(sizeof(struct node));
myqueue->front = new;
}
int init(Queuepointer q){
q = (Queuepointer)malloc(sizeof(struct queue));
q->front = NULL;
q->back = NULL;
}
The idea is that the queue struct 'contains' the first and last nodes in a queue, and when a node is created, myqueue is updated. However, I cannot even get to that part (pop and push are written but omitted for brevity). The code is segfaulting at the line
myqueue->front = new;
with the following gdb output:
Program received signal SIGSEGV, Segmentation fault.
0x08048401 in main () at queue.c:27
27 myqueue->front = new;
Any idea what I'm doing wrong?
When you call init:
int init(Queuepointer q){
q = (Queuepointer)malloc(sizeof(struct queue));
q->front = NULL;
q->back = NULL;
}
You're passing a pointer to a queue into the function, and initializing where that pointer points (in memory) within the function. By setting q = ..., you're assigning a new value to q.
Unfortunately, the calling function does not see this. You need to pass a pointer to a pointer instead:
int init(Queuepointer * qp){
Queuepointer q = (Queuepointer)malloc(sizeof(struct queue));
q->front = NULL;
q->back = NULL;
// Set qp:
*qp = q;
}
Then change the calling function:
init(&myqueue);
init(myqueue); passes by value a pointer to unallocated memory.
init does nothing on it, consequently (instead, writing random things at random location).
Then, myqueue->stuff does it again.
You should have used pointer to pointer.
Init will receive queue**, and called as init(&myqueue).
Inside, *myqueue=()malloc stuff
Also, I recommend you against these typedefs. They are rather bad style.
The first problem I see is that the "init" function writes the allocated pointer in "q", that is NOT your original "myqueue". Remember that C passes its arguments by value. A possible correction (not perfect, just a hint) is
Queuepointer init(void)
Queuepointer q;
q = (Queuepointer)malloc(sizeof(struct queue));
q->front = NULL;
q->back = NULL;
return q;
}
`
And in "main":
myqueue = init();
Also beware that in your program you don't initialize the element allocated by malloc. malloc doesn't in general clean the memory it allocates.
Regards
You are passing myqueue by value so the allocation happened at init() is for the copy of myqueue not to myqueue.
So the correct version is:
int init(Queuepointer* q){
*q = (Queuepointer)malloc(sizeof(struct queue));
*q->front = NULL;
*q->back = NULL;
}
and you can call init() from main
init(&myqueue);
int init(Queuepointer q){
q = (Queuepointer)malloc(sizeof(struct queue));
q->front = NULL;
q->back = NULL;
}
Minor nitpick, but your init function has no return value so perhaps change it to:
void init(Queuepointer *q) {
or
int init(Queuepointer * qp){
Queuepointer q = (Queuepointer)malloc(sizeof(struct queue));
q->front = NULL;
q->back = NULL;
*qp = q;
if(q) {
return 1;
} else return 0;
}
Adjust according to how you want to perform error checking.