Queue performance wise which is better implementat

2019-03-20 17:29发布

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;
}

3条回答
兄弟一词,经得起流年.
2楼-- · 2019-03-20 18:16

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.

查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-03-20 18:18

If there is an upper bound on the total number of elements you're going to store in the queue, use a circular array. This eliminates the need to resize an array, when continuously adding elements to its end.

查看更多
Evening l夕情丶
4楼-- · 2019-03-20 18:20

Even if you have many elements, the array implementation is probably the fastest. For inspiration, I took a look at GCC's C++ dequeue. It stores the queue as an array of arrays. I am not sure if the iterators wrap around as in circular buffer. The array implementation also has fast random access, should you need it later.

查看更多
登录 后发表回答