queue.h的链表使用

from  https://segmentfault.com/a/1190000000596749

在FreeBSD中有queue.h这样一个头文件(Linux也有),它定义了一系列的宏操作,实现了链表,尾队列和循环链表。其中,链表的功能最为简单,效率是最好的。
我们先看一下系统提供的链表的操作:

    LIST_ENTRY(TYPE)   
    LIST_HEAD(HEADNAME,TYPE)
    LIST_INIT(LIST_HEAD *head)
    LIST_INSERT_AFTER(LIST_ENTRY *listelm,TYPE *elm,LIST_ENTRY NAME)
    LIST_INSERT_HEAD(LIST_HEAD *head,TYPE *elm,LIST_ENTRY NAME)
    LIST_REMOVE(TYPE *elm,LIST_ENTRY NAME)

其中LIST_HEAD、LIST_INIT、LIST_INSERT_AFTER、LIST_INSERT_HEAD、LIST_REMOVE从名字可以看出其功能,但是它们的参数就不这么好理解了。下面我们来看一个例子和部分宏的源码,弄明白这组宏的使用方法。
部分宏源码

#define LIST_ENTRY(type)                                                \
struct {                                                                \
        struct type *le_next;   /** next element */                     \
        struct type **le_prev;  /** address of previous next element */ \
}
#define LIST_HEAD(name, type)                                           \
struct name {                                                           \
        struct type *lh_first;  /** first element */                    \
}
#define LIST_INSERT_HEAD(head, elm, field) do {                         \
        if (((elm)->field.le_next = (head)->lh_first) != NULL)          \
                (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
        (head)->lh_first = (elm);                                       \
        (elm)->field.le_prev = &(head)->lh_first;                       \
} while (/**CONSTCOND*/0)



example

#include<stdio.h>
#include<stdlib.h>
#include<sys/queue.h>

struct element{
    int num;
    /*LIST_ENTRY 创建了一个以element为名的结构体定义
     这个结构体含有向后指针和向前指针
     le_next 和 le_prev
     并且声明了一个类型为element的变量elements
     */
    LIST_ENTRY(element) elements;
};
int main(void){
    /*LIST_HEAD 会自动构建一个名为listh的结构体,
      里面含有一个element指针 *lh_first
      所以 先调用LIST_HEAD之后,才会生成struct声明,后面才可以使用
      关于listh的指针
     */
    LIST_HEAD(listh,element) head; 
    struct listh *headp;
    struct element *n1,*np;
    int i=0;
    LIST_INIT(&head);
    printf("开始\n");
    do{

        printf("输入一个数字,输入0则结束\n");
        scanf("%d",&i);

        n1 = (struct element*)malloc(sizeof(struct element));
        n1->num = i;

        /*
       对于LIST_INSERT_HEAD为何需要用指针域作为参数,
       因为指针域的名字是用户自己定义的,函数内部并不知道,
       所以需要作为参数传入,并且在宏之内,可以连接字符串实现
       类似反射的功能。
       */

        LIST_INSERT_HEAD(&head,n1,elements);
    }while(i);
    for(np=(head).lh_first;np!=NULL;np=np->elements.le_next){
        printf("%d ",np->num);
    }   
    printf("\n");
    return 0;
}




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以帮你编写 queue.h,这提供一份链式队列的实现代码,你可以参考一下: ```c++ #ifndef QUEUE_H_ #define QUEUE_H_ #include <iostream> template<typename T> class Queue { private: struct Node { T item; Node* next; Node(const T& i, Node* n = nullptr) : item(i), next(n) {} }; Node* front; Node* rear; int size; public: Queue() : front(nullptr), rear(nullptr), size(0) {} ~Queue() { Node* temp; while (front != nullptr) { temp = front; front = front->next; delete temp; } } bool is_empty() const { return size == 0; } int get_size() const { return size; } void clear() { *this = Queue(); } void enqueue(const T& item) { Node* temp = new Node(item); if (front == nullptr) { front = temp; rear = temp; } else { rear->next = temp; rear = temp; } ++size; } T dequeue() { if (is_empty()) { std::cerr << "Queue is empty." << std::endl; exit(EXIT_FAILURE); } T item = front->item; Node* temp = front; front = front->next; delete temp; --size; return item; } T peek() const { if (is_empty()) { std::cerr << "Queue is empty." << std::endl; exit(EXIT_FAILURE); } return front->item; } }; #endif ``` 然后你可以在测试程序lab9_3.cpp中创建一个整型队列对象,并进行入队、出队操作,代码如下: ```c++ #include <iostream> #include "queue.h" int main() { Queue<int> q; q.enqueue(1); q.enqueue(2); q.enqueue(3); q.enqueue(4); q.enqueue(5); while (!q.is_empty()) { std::cout << q.dequeue() << " "; } std::cout << std::endl; return 0; } ``` 输出结果为: ``` 1 2 3 4 5 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值