菜鸟nginx源码剖析数据结构篇(二) 双向链表ngx_queue_t

本文深入剖析了nginx源码中的关键数据结构——双向链表ngx_queue_t,详细介绍了其设计理念和实现原理,帮助读者更好地理解和使用nginx源码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

nginx源码剖析数据结构篇(二) 双向链表ngx_queue_t

 

  • Author:Echo Chen(陈斌)

  • Email:chenb19870707@gmail.com

  • Blog:Blog.youkuaiyun.com/chen19870707

  • Date:October 20h, 2014

     

    1.ngx_queue优势和特点

     

    ngx_queue作为顺序容器链表,它优势在于其可以高效地执行插入、删除、合并操作,在插入删除的过程中,只需要修改指针指向,而不需要拷贝数据,因此,对于频繁修改的容器很适合。此外,相对于STL list,它还具有以下特点:

    • 自身实现了排序功能
    • 轻量级,不负责内存的分配
    • 自身支持两个链表的合并

    2.源代码位置

     

    头文件:http://trac.nginx.org/nginx/browser/nginx/src/core/ngx_queue.h

    源文件:http://trac.nginx.org/nginx/browser/nginx/src/core/ngx_queue.c

     

    3.数据结构定义

     

       1: typedef struct ngx_queue_s  ngx_queue_t;
       2:  
       3: struct ngx_queue_s {
         
         
       4:     ngx_queue_t  *prev;
       5:     ngx_queue_t  *next;
       6: };

     

        可以看到,它的结构非常简单,仅有两个成员:prev、next,这样对于链表中元素来说,空间上只增加了两个指针的消耗。

     

    4.初始化ngx_queue_init

     

       1: //q 为链表容器结构体ngx_queue_t的指针,将头尾指针指向自己
       2: #define ngx_queue_init(q)                                                     \
       3:     (q)->prev = q;                                                            \
       4:     (q)->next = q

     

    初始状态的链表如图所示:

    image

     

    5.判断链表容器是否为空ngx_queue_empty

     

    判断方法非常简单,即判断链表的prev指针是否指向自己,如上图所示

       1: #define ngx_queue_empty(h)                                                    \
       2:     (h == (h)->prev)

     

     

    6.头部插入ngx_queue_insert_head

     

       1: //h为链表指针,x为要插入的元素
       2: #define ngx_queue_insert_head(h, x)                                           \
       3:     (x)->next = (h)->next;                                                    \
       4:     (x)->next->prev = x;                                                      \
       5:     (x)->prev = h;                                                            \
       6:     (h)->next = x

     

    标准的双链表插入四步操作,如图所示:

    image

     

    7.尾部插入ngx_queue_insert_tail

     

    与头部插入类似,只是第一步给的h->prev ,即为最后一个结点:

     

       1: #define ngx_queue_insert_tail(h, x)                                           \
       2:     (x)->prev = (h)->prev;                                                    \
       3:     (x)->prev->next = x;                                                      \
       4:     (x)->next = h;                                                            \
       5:     (h)->prev = x

     

    8.链表删除ngx_queue_remove

     

    x为要删除的结点,将x的下一个的结点的prev指针指向x的上一个结点,再将x的前一个结点的next指针指向x的下一个结点,常规链表双链表结点删除操作,不处理内存释放

     

       1: #define ngx_queue_remove(x)                                                   \
       2:     (x)->next->prev = (x)->prev;                                              \
       3:     (x)->prev->next = (x)->next
       4:  
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值