C语言实现的双向队列,可以组织多种结构体元素成为队列

这篇博客解析了MCAPI中的队列实现,关注其如何仅通过前驱和后继指针管理不同类型的元素,展示了环形队列的简洁状态维护。作者探讨了`enqueue`、`remove`和`dequeue`操作背后的逻辑,对于队列原理和高效编程有深入见解。

看MCAPI的某个实现代码中的队列,有点疑惑, 这个队列的实现怎么没有队列元素的数据呢,队头呢,队尾呢? 为何QNode只有前驱和后继的指针而已。看懂之后,还是要佩服一下,这种实现方式可以管理多种类型的数据。且这是一个环形队列,维护的状态很简洁。

#include <openmcapi.h>

typedef struct MCAPI_QNode_Struct
{
    struct MCAPI_QNode_Struct      *flink;
    struct MCAPI_QNode_Struct      *blink;
} MCAPI_QNODE;

/*************************************************************************
*
*   FUNCTION
*
*       mcapi_enqueue
*
*   DESCRIPTION
*
*       Enqueues an entry onto a given queue.
*
*   INPUTS
*
*       *queue_ptr              Pointer to the queue to which the entry
*                               is being enqueued.
*       *entry                  Pointer to the new queue entry.
*
*   OUTPUTS
*
*       None.
*
*************************************************************************/
void mcapi_enqueue(void *queue_ptr, void *entry)
{
    MCAPI_QNODE     *hdr = queue_ptr;
    MCAPI_QNODE     *item = entry;

    /* Set item's flink to point at NULL */
    item->flink = MCAPI_NULL;

    /* If there is currently a node in the linked list, we want add
     * item after that node
     */
    if (hdr->flink)
    {
        /* Make the last node's flink point to item */
        hdr->blink->flink = item;

        /* Make item's blink point to the old last node */
        item->blink = hdr->blink;

        /* Make hdr's blink point to the new last node, item */
        hdr->blink = item;
    }

    /* If the linked list was empty, we want both the hdr's flink and
     * the hdr's blink to point to item.  Both of item's links will
     * point to NULL, as there are no other nodes in the list
     */
    else
    {
        hdr->flink = hdr->blink = item;
        item->blink = MCAPI_NULL;
    }

}

/*************************************************************************
*
*   FUNCTION
*
*       mcapi_remove
*
*   DESCRIPTION
*
*       Removes an entry from a given queue.
*
*   INPUTS
*
*       *queue_ptr              Pointer to the queue from which the entry
*                               is being removed.
*       *entry                  Pointer to the queue entry to remove.
*
*   OUTPUTS
*
*       A pointer to the item that was removed.
*
*************************************************************************/
void *mcapi_remove(void *queue_ptr, void *entry)
{
    MCAPI_QNODE     *hdr = queue_ptr;
    `
    MCAPI_QNODE     *ent;

    /*  Search the linked list until item is found or the end of the list
     *  is reached.
     */
    for (ent = hdr->flink;( (ent) && (ent != item) ); ent = ent->flink)
        ;

    /*  If the item was found. */
    if (ent)
    {
        /* If we are deleting the list head, this is just a dequeue operation */
        if (hdr->flink == item)
            mcapi_dequeue(hdr);

        /*  If we are deleting the list tail, we need to reset the tail pointer
         *  and make the new tail point forward to 0.
         */
        else if (hdr->blink == item)
        {
            hdr->blink = item->blink;
            hdr->blink->flink = MCAPI_NULL;
        }

        /* We are removing this entry from the middle of the list */
        else
        {
            item->blink->flink = item->flink;
            item->flink->blink = item->blink;
        }
    }

    return (ent);

}

/*************************************************************************
*
*   FUNCTION
*
*       mcapi_dequeue
*
*   DESCRIPTION
*
*       Removes and returns the first entry in a queue.
*
*   INPUTS
*
*       *queue_ptr              Pointer to the queue from which the entry
*                               is being removed.
*
*   OUTPUTS
*
*       Pointer to the entry removed from the queue.
*
*************************************************************************/
void *mcapi_dequeue(void *queue_ptr)
{
   MCAPI_QNODE *hdr = queue_ptr;
   MCAPI_QNODE *ent;

   /* Create a pointer to the first node in the linked list */
   ent = hdr->flink;

   /* If there is a node in the list we want to remove it. */
   if (ent)
   {
       /* Make the hdr point the second node in the list */
       hdr->flink = ent->flink;

       /*  If there was a second node, we want that node's blink to at 0. */
       if (hdr->flink)
           hdr->flink->blink = MCAPI_NULL;

       /* Clear the next and previous pointers.*/
       ent->flink = ent->blink = MCAPI_NULL;
   }

   /* Return a pointer to the removed node */
   return (ent);

}  /* mcapi_dequeue */

从enqueue函数来看,入队的指针有个强制转换的过程。那么就会要求入队的指针一定要空出两个个指针的位置,用于被转换出前驱和后继的指针。

     看看将会组织成队列的buffer结构体和request结构体的定义,可以看出特意定义出前驱和后继两个指针。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值