Which way gives the faster enqueueing and dequeuing when I have to insert very few elements, Is array better than a linked list?
I need to insert few element and I have to remove and read that removed element from queue. If it is array I may have to modify the indexes every time I remove an element. Inserting and deleting may happen simultaneously also.
Which one is better from below case?
typedef struct{
mylist list;
struct mylistQ *next;
}mylistQ;
Array Code
static mylist myListQ[QUEUESIZE+1];
int qLast = 0;
void enqueue_element(mylist qItem)
{
myListQ[qLast] = qItem;
qLast++;
}
mylist dequeue_element()
{
retryq:
if(qLast >0) {
mylist qReturn = myListQ[0];
int i;
for (i = 0; i < qLast - 1; i++){
myListQ[i] = myListQ[i + 1];
}
qLast--;
return qReturn;
}
else {
goto retryq;
}
}
Linked List
int qLast = 0;
mylistQ *headElement = NULL;
mylistQ *tailElement = NULL;
void enqueue_element(mylist *List)
{
mylistQ *newnode;
newnode=(mylistQ*)av_malloc(sizeof(mylistQ));
newnode->next=NULL;
newnode->list=*List;
qLast++;
if(headElement==NULL && tailElement==NULL)
{
headElement=newnode;
tailElement=newnode;
}
else
{
tailElement->next=newnode;
tailElement=newnode;
}
}
mylist dequeue_element()
{
mylistQ *delnode; /* Node to be deleted */
mylist Dellist;
if(headElement==NULL && tailElement==NULL){
LOg( "Queue is empty to delete any element");
}
else
{
Log("In dequeue_picture queue is not empty");
delnode=headElement;
headElement=headElement->next;
if (!headElement){
tailElement=NULL;
}
Dellist = delnode->list;
av_free(delnode);
qLast--;
}
return Dellist;
}
It depends on how many operations you'll be performing and exactly how the array version is implemented.
If you're doing comparatively few operations, ie less than 1000 or so enqueue/dequeues in total, then an array would be faster because it is contiguous in memory. Maintain a pointer to the front and a pointer to the back, always add at the back and dequeue at the front.
On the other hand even if the list is no longer than 30 or so elems ever, if this has to persist of a long period you won't have any array resizing issues which is a potential problem with the array.
Linked list is guaranteed excellent performance, array you have to watch for resizing.
EDIT: As mentioned by @Hans Passant, arrays are fast because they have CPU cache locality. As long as your array is small, your hardware will optimize performance such that the memory associated with storing the array will be kept in your L2. Indices likely in registers. This is REALLY fast. Judging by the fact that you won't need many elements, an array would be ideal in this case. And yes, you will have to modify indices when you move elements, but this is actually an extremely fast operation since if you build the code with optimization the indices will be stored in registrars.
Here's the catch though, you mention you may have to do both enqueue and dequeue at the same time, by this do you mean it's parallel ie multiple threads accessing the memory? If this is the case, arrays would still be faster, but you'll see something like a 800 fold decrease in performance. Why? because no longer can the processor buffer the memory associated with your queue on the die, but it must be stored in main memory. In addition, you're running the risk of creating a race condition between threads. Imagine if one thread tried to dequeue while another tried to enqueue and there was only one elem in the list, you could have disaster. Either way, if this application is very perfromance driven, be sure to compile (assuming gcc) with the NDEBUG and -O3 flags on.
Second Edit: Looking at the code, and looking below at other answers, I'd suggest making your array code more efficient and turning it into a circular array since it sounds like you have an upper bound on the number of elements. As a side note, you're current array implementation is extremely inefficient, every time you remove you copy forward the rest of the Queue, this makes no sense, just increment a int pointer to the "first" index.
Pseudo Code:
int ciruclarArray[SIZE];
int front = 0;
int back = 0;
void enqueue(int elem)
{
circularArray[back] = elem;
if(back < (circularArray.length - 1))
back++;
else
back = 0;
return elem;
}
int dequeue()
{
int toReturn = circularArray[front];
//do same check for incrementing as enqueue
return toReturn;
}
just don't forget to do error checking for the normal stuff.