1. 程式人生 > >libevent(二)尾隊列 && 最小堆

libevent(二)尾隊列 && 最小堆

結構 pty signed don eap main .com first 存儲

本文主要研究libevent中用來存儲事件的兩個結構體。

尾隊列

具體定義位於queue.h中。

#define    TAILQ_HEAD(name, type)                        struct name {                                    struct type *tqh_first;    /* first element */                struct type **tqh_last;    /* addr of last next element */        }

#define    TAILQ_ENTRY(type)                        struct
{ struct type *tqe_next; /* next element */ struct type **tqe_prev; /* address of previous next element */ } #define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) #define TAILQ_FIRST(head) ((head)->tqh_first) #define
TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) #define TAILQ_INIT(head) do { \ TAILQ_FIRST((head)) = NULL; (head)->tqh_last = &TAILQ_FIRST((head)); } while (0) #define TAILQ_INSERT_TAIL(head, elm, field) do { \ TAILQ_NEXT((elm), field)
= NULL; (elm)->field.tqe_prev = (head)->tqh_last; *(head)->tqh_last = (elm); (head)->tqh_last = &TAILQ_NEXT((elm), field); } while (0) #define TAILQ_INSERT_HEAD(head, elm, field) do { if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) TAILQ_FIRST((head))->field.tqe_prev = &TAILQ_NEXT((elm), field); else (head)->tqh_last = &TAILQ_NEXT((elm), field); TAILQ_FIRST((head)) = (elm); (elm)->field.tqe_prev = &TAILQ_FIRST((head)); } while (0) #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL) TAILQ_NEXT((elm), field)->field.tqe_prev = &TAILQ_NEXT((elm), field); else { (head)->tqh_last = &TAILQ_NEXT((elm), field); } TAILQ_NEXT((listelm), field) = (elm); (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); } while (0) #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; TAILQ_NEXT((elm), field) = (listelm); *(listelm)->field.tqe_prev = (elm); (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); } while (0) #define TAILQ_REMOVE(head, elm, field) do { if ((TAILQ_NEXT((elm), field)) != NULL) TAILQ_NEXT((elm), field)->field.tqe_prev = (elm)->field.tqe_prev; else { (head)->tqh_last = (elm)->field.tqe_prev; } *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); } while (0)

從定義可以看出,尾隊列是一個雙向鏈表,具體表現為:

技術分享

一個小DEMO:

技術分享
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>

#define LIST_SIZE 5

// 聲明頭結點
TAILQ_HEAD(event_list, event);
// 聲明元素結點
struct event {
    int value;
    TAILQ_ENTRY(event) field;
};

int main(int argc, char **argv) {
    event_list *list = (event_list*)malloc(sizeof(event_list));
    TAILQ_INIT(list);
    
    event *item;
    for (int i = 0; i < LIST_SIZE; i++) {
        item = (event*)malloc(sizeof(event));
        item->value = i;
        item->field.tqe_next = NULL;
        item->field.tqe_prev = NULL;
        
        TAILQ_INSERT_TAIL(list, item, field);
    }
    
    printf("當前list: ");
    for (item = list->tqh_first; item; item = item->field.tqe_next) {
        printf("%d ", item->value);
    }
    printf("\n");
    
    event **test = list->tqh_first->field.tqe_prev;
    if (test == &list->tqh_first) {
        printf("guess right\n");
    }
    
    printf("尾部插入結點: 10\n");
    item = (event*)malloc(sizeof(event));
    item->value = 10;
    item->field.tqe_next = NULL;
    item->field.tqe_prev = NULL;
    TAILQ_INSERT_TAIL(list, item, field);
    
    printf("當前list: ");
    for (item = list->tqh_first; item; item = item->field.tqe_next) {
        printf("%d ", item->value);
    }
    printf("\n");
    
    printf("頭部插入結點: 20\n");
    item = (event*)malloc(sizeof(event));
    item->value = 20;
    item->field.tqe_next = NULL;
    item->field.tqe_prev = NULL;
    TAILQ_INSERT_HEAD(list, item, field);
    
    printf("當前list: ");
    for (item = list->tqh_first; item; item = item->field.tqe_next) {
        printf("%d ", item->value);
    }
    printf("\n");
    
    printf("在值為3的結點之後插入結點: 30\n");
    for (item = list->tqh_first; item; item = item->field.tqe_next) {
        if (item->value == 3) {
            event *new_item = (event*)malloc(sizeof(event));
            new_item->value = 30;
            new_item->field.tqe_next = NULL;
            new_item->field.tqe_prev = NULL;
            TAILQ_INSERT_AFTER(list, item, new_item, field);
        }
    }
    
    printf("當前list: ");
    for (item = list->tqh_first; item; item = item->field.tqe_next) {
        printf("%d ", item->value);
    }
    printf("\n");
    
    printf("在值為1的結點之前插入結點: 40\n");
    for (item = list->tqh_first; item; item = item->field.tqe_next) {
        if (item->value == 1) {
            event *new_item = (event*)malloc(sizeof(event));
            new_item->value = 40;
            new_item->field.tqe_next = NULL;
            new_item->field.tqe_prev = NULL;
            TAILQ_INSERT_BEFORE(item, new_item, field);
        }
    }
    
    printf("當前list: ");
    for (item = list->tqh_first; item; item = item->field.tqe_next) {
        printf("%d ", item->value);
    }
    printf("\n");
    
    printf("刪除值為3的結點\n");
    for (item = list->tqh_first; item; item = item->field.tqe_next) {
        if (item->value == 3) {
            TAILQ_REMOVE(list, item, field);
        }
    }
    
    printf("當前list: ");
    for (item = list->tqh_first; item; item = item->field.tqe_next) {
        printf("%d ", item->value);
    }
    printf("\n");
    
    printf("Done\n");
}
View Code

最小堆

typedef struct min_heap
{
    struct event** p;
    unsigned n, a;
} min_heap_t;

暫時不表。

參考資料:

do {...} while (0) 的用途匯總(歡迎補充)

libevent(二)尾隊列 && 最小堆