list

list.h

这个list.h其实是linux内核中链表实现的精简版(只需要一个头文件),linux提供的这套接口更像是构造list的零部件。用户可以选择直接用它定制化自己的 list型数据结构,甚至可以实现一个更为 高层次的、通用的 list接口(如下面的clist)

#ifndef _LIST_H_
#define _LIST_H_
#ifdef __cplusplus
extern "C"
{
#endif

struct list_node
{
    struct list_node *next;
    struct list_node *prev;
};

/**
* ListNodeToItem - get the struct for this entry
* @node:    the &struct list_node pointer.
* @container:    the type of the struct this is embedded in.
* @member:    the name of the list_struct within the struct.
*/
#define ListNodeToItem(node, container, member) \
    (container *) (((char*) (node)) - ((unsigned long) &((container *)0)->member))

#define ListDeclare(name) \
    struct list_node name = { \
        .next = &name, \
        .prev = &name, \
    }

/**
* ListForEach    -    iterate over a list
* @node:    the &struct list_node to use as a loop cursor.
* @list:    the head for your list.
*/
#define ListForEach(node, list) \
    for (node = (list)->next; node != (list); node = node->next)

/**
* ListForEachReverse    -    iterate over a list backwards
* @node:    the &struct list_node to use as a loop cursor.
* @list:    the head for your list.
*/
#define ListForEachReverse(node, list) \
    for (node = (list)->prev; node != (list); node = node->prev)

/**
* ListForEachSafe - iterate over a list safe against removal of list entry
* @node:    the &struct list_node to use as a loop cursor.
* @n:        another &struct list_node to use as temporary storage
* @list:    the head for your list.
*/
#define ListForEachSafe(node, n, list) \
    for (node = (list)->next, n = node->next; \
         node != (list); \
         node = n, n = node->next)

static inline void ListInit(struct list_node *node)
{
    node->next = node;
    node->prev = node;
}

/**
* ListAddTail - add a new entry
* @head: list head to add it before
* @item: new entry to be added
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void ListAddTail(struct list_node *head, struct list_node *item)
{
    item->next = head;
    item->prev = head->prev;
    head->prev->next = item;
    head->prev = item;
}

/**
* ListAddHead - add a new entry
* @head: list head to add it after
* @item: new entry to be added
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void ListAddHead(struct list_node *head, struct list_node *item)
{
    item->next = head->next;
    item->prev = head;
    head->next->prev = item;
    head->next = item;
}

/**
* ListAppend - let list2(head2) append to the tail of list1(head1)
*/
static inline void ListAppend(struct list_node *head1, struct list_node *head2)
{
    head2->prev->next = head1;
    head2->next->prev = head1->prev;
    head1->prev->next = head2->next;
    head1->prev = head2->prev;

    head2->prev = head2;
    head2->next = head2;
}

static inline void ListReverse(struct list_node *head)
{
    struct list_node *pNode = head;
    struct list_node *pTmp = NULL;
    while(pNode->next != head)
    {
        //store the next node
        pTmp = pNode->next;
        //swap
        //pTmp = pNode->next;
        pNode->next = pNode->prev;
        pNode->prev = pTmp;

        pNode = pTmp;
    }
    //last swap
    pTmp = pNode->next;
    pNode->next = pNode->prev;
    pNode->prev = pTmp;
}

/*
* ZX_ListRemove - delete a list entry
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void ListRemove(struct list_node *item)
{
    item->next->prev = item->prev;
    item->prev->next = item->next;
}

#define ListIsEmpty(list) ((list) == (list)->next)
#define ListHead(list) ((list)->next)
#define ListTail(list) ((list)->prev)

#ifdef __cplusplus
}
#endif
#endif //LIST_H_

直接使用 list.h

在头文件中,定义一个node,一个manager

//自己实现的一个stack(queue也是可以实现的)
typedef struct {
    pthread_mutex_t lock;           //这里应该有一个mutex lock的,但是写的时候忘记加了
    unsigned int u32StackSize;
    struct zxlist_node listNode;
}FRAME_UI_STACK_MGR;                 //stack manager结构体

typedef struct {
    UI_FRAME_S *pUIFrame;
    struct zxlist_node listNode;
}FRAME_UI_STACK_NODE;

在.c文件中,

static FRAME_UI_STACK_MGR gstFrameUIStack = {
    .lock = PTHREAD_MUTEX_INITIALIZER,
};

static int frameUIStackInit() {
    gstFrameUIStack.u32StackSize = 0;
    ZX_ListInit(&gstFrameUIStack.listNode);
    return 0;
}

static int frameUIStackDeinit() {//descroy the stack
    zxlist_node *pListNode = NULL;
    FRAME_UI_STACK_NODE *pStackNode = NULL;
    while(!ZX_ListEmpty(&gstFrameUIStack.listNode)) {
        pListNode = ZX_ListTail(&gstFrameUIStack.listNode);
        pStackNode = ZX_ListNodeToItem(pListNode, FRAME_UI_STACK_NODE, listNode);
        ZX_ListRemove(pListNode);
        free(pStackNode);
    }
    gstFrameUIStack.u32StackSize = 0;
    return 0;
}

static int frameUIStackPush(UI_FRAME_S *pUIFrame) {
    if(pUIFrame == NULL) {
        printf("frameUIStackPush error: invalid param\n");
        return -1;
    }
    FRAME_UI_STACK_NODE *pUINode = (FRAME_UI_STACK_NODE *)malloc(sizeof(FRAME_UI_STACK_NODE));
    if(pUINode == NULL) {
        printf("frameUIStackPush add node error: no more availiable mem\n");
        return -1;
    }
    pUINode->pUIFrame = pUIFrame;
    ZX_ListAddTail(&gstFrameUIStack.listNode,&(pUINode->listNode));    //add to tail
    gstFrameUIStack.u32StackSize++;
    return 0;
}

static int frameUIStackTop(UI_FRAME_S **ppUIFrame) {
    if(ppUIFrame == NULL) {
        printf("frameUIStackTop error: invalid param\n");
        return -1;
    }
    if(gstFrameUIStack.u32StackSize == 0) {
        if(ZX_ListEmpty(&gstFrameUIStack.listNode)) {//confirm
            printf("frameUIStackTop stack is empty!\n");
            *ppUIFrame = NULL;
            return 0;
        } else {
            printf("frameUIStackTop error!\n");
            *ppUIFrame = NULL;
            return -1;
        }
    }
    zxlist_node *pListNode = ZX_ListTail(&gstFrameUIStack.listNode);        //just get the tail
    FRAME_UI_STACK_NODE *pStackNode = ZX_ListNodeToItem(pListNode, FRAME_UI_STACK_NODE, listNode);
    *ppUIFrame = pStackNode->pUIFrame;
    return 0;
}

static int frameUIStackPop(UI_FRAME_S **ppUIFrame) {
    if(gstFrameUIStack.u32StackSize == 0) {
        if(ZX_ListEmpty(&gstFrameUIStack.listNode)){
            printf("frameUIStackPop stack is empty!\n");
            *ppUIFrame = NULL;
            return 0;
        } else {
            printf("frameUIStackPop error!\n");
            *ppUIFrame = NULL;
            return -1;
        }
    }
    zxlist_node *pListNode = ZX_ListTail(&gstFrameUIStack.listNode);    //get the tail
    FRAME_UI_STACK_NODE *pStackNode = ZX_ListNodeToItem(pListNode, FRAME_UI_STACK_NODE, listNode);
    if(ppUIFrame != NULL) {//if param is null, just discard top element
        *ppUIFrame = pStackNode->pUIFrame;
    }
    ZX_ListRemove(pListNode);                                                                       //remove the tail
    free(pStackNode);
    gstFrameUIStack.u32StackSize--;
    return 0;
}

数组实现的stack和queue比链表效率更高一点

  • 数组实现的stack应该很简单
  • 数组实现的queue分为两种:
    • 使用环形队列,效率高,但需要考虑wrap的情况 (RingBuf)
    • 不用环形队列,使用memmove,效率有折损但简单(bufQueue)
      list、stack、fifo(即queue)都属于线性结构,stack和fifo可以看作阉割版的list

cList.c,这是在学习了《c 接口与实现》第7章 后弄的一个类 lisp 链表 的实现

#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "cList.h"

//将一个数据push到list的head
clist List_push(clist list, void *x)
{
    unsigned int flag=0;
    clist listTmp = NULL;
    clistNode *pNodeTmp = NULL;
    if(!list)
    {    //new malloc a list manager node and init
        listTmp = (clist)malloc(sizeof(struct clistManager));
        if(!listTmp)
            goto FAIL_1;
        ListInit(&listTmp->listNode);
        listTmp->u32ListSize = 0;
        flag = 1;
    }
    else
        listTmp = list;

    //new list node and init
    pNodeTmp = (clistNode *)malloc(sizeof(clistNode));
    if(!pNodeTmp)
        goto FAIL_2;
    ListInit(&pNodeTmp->listNode);
    pNodeTmp->data = x;

    //add list node to clist manager(header)
    ListAddHead(&listTmp->listNode, &pNodeTmp->listNode);
    listTmp->u32ListSize++;
    return listTmp;

FAIL_2:
    if(flag)
        free(listTmp);
FAIL_1:
    return NULL;
}

//构造一个list,应该以NULL或者其他为false的值结尾
clist List_list(void *x, ...)
{
    va_list ap;
    va_start(ap, x);

    clist listTmp = NULL;
    clistNode *pNodeTmp = NULL;
    struct list_node *plistNode = NULL;

    //new malloc a list manager node and init
    listTmp = (clist)malloc(sizeof(struct clistManager));
    if(!listTmp)
        goto FAIL_1;
    ListInit(&listTmp->listNode);
    listTmp->u32ListSize = 0;

    for ( ; x; x = va_arg(ap, void *))
    {
        //new list node and init
        pNodeTmp = (clistNode *)malloc(sizeof(clistNode));
        if(!pNodeTmp)    // TODO: this may cause memleak
            goto FAIL_2;
        ListInit(&pNodeTmp->listNode);
        pNodeTmp->data = x;

        ListAddTail(&listTmp->listNode, &pNodeTmp->listNode);
        listTmp->u32ListSize++;
    }
    va_end(ap);
    return listTmp;

FAIL_2:
    List_free(&listTmp);
FAIL_1:
    return NULL;
}

clist List_append(clist list, clist tail)
{
    if(!list)
        return tail;

    if(tail)
    {
        ListAppend(&list->listNode, &tail->listNode);
        list->u32ListSize += tail->u32ListSize;
        tail->u32ListSize = 0;
    }
    return list;
}

clist List_copy(clist list)
{
    clist listTmp = NULL;
    clistNode *pNodeTmpSrc = NULL;
    clistNode *pNodeTmpDst = NULL;

    if(list)
    {
        //new malloc a list manager node and init
        listTmp = (clist)malloc(sizeof(struct clistManager));
        if(!listTmp)
            goto FAIL_1;
        ListInit(&listTmp->listNode);
        listTmp->u32ListSize = 0;

        struct list_node *plistNode = NULL;
        ListForEach(plistNode,&list->listNode)
        {
            pNodeTmpSrc = ListNodeToItem(plistNode, clistNode, listNode);
            //new list node and init
            pNodeTmpDst = (clistNode *)malloc(sizeof(clistNode));
            if(!pNodeTmpDst)
                goto FAIL_2;
            ListInit(&pNodeTmpDst->listNode);
            pNodeTmpDst->data = pNodeTmpSrc->data;
            //insert
            ListAddTail(&listTmp->listNode, &pNodeTmpDst->listNode);
            listTmp->u32ListSize++;
        }
    }
    return listTmp;

FAIL_2:
    List_free(&listTmp);
FAIL_1:
    return NULL;
}

clist List_pop(clist list, void **x)
{
    struct list_node *plistNode = NULL;
    clistNode *pNodeTmp = NULL;
    if (list && !ListIsEmpty(&list->listNode))
    {
        plistNode = ListHead(&list->listNode);
        pNodeTmp = ListNodeToItem(plistNode, clistNode, listNode);
        if (x)
            *x = pNodeTmp->data;
        ListRemove(plistNode);
        free(pNodeTmp);
        list->u32ListSize--;
    }
    return list;
}

//NOTE :param list and returned list both reversed!
clist List_reverse(clist list)
{
    if(list)
        ListReverse(&list->listNode);
    return list;
}

int List_length(clist list)
{
    int n=0;
    if(list)
        n = list->u32ListSize;
    return n;
}

void List_free(clist *plist)
{
    struct list_node *plistNode = NULL;
    clistNode *pNodeTmp = NULL;
    clist list = NULL;
    if (plist)
    {
        list = *plist;
        if(list)
        {
            while(!ListIsEmpty(&list->listNode))
            {
                plistNode = ListHead(&list->listNode);
                pNodeTmp = ListNodeToItem(plistNode, clistNode, listNode);
                ListRemove(plistNode);
                free(pNodeTmp);
                list->u32ListSize--;
            }
            free(list);
        }
        *plist = NULL;
    }
}

void List_map(clist list, void apply(void **x,int index, void *cl), void *cl)
{
    struct list_node *plistNode = NULL;
    clistNode *pNodeTmp = NULL;
    int i=0;
    if(apply && list)
    {
        ListForEach(plistNode,&list->listNode)
        {
            //apply 使用的是指向 first 的指针,因此可能改变 first 指针的指向
            pNodeTmp = ListNodeToItem(plistNode, clistNode, listNode);
            apply(&pNodeTmp->data,i++,cl);    //
        }
    }
}

void **List_toArray(clist list, void *end)
{
    int i=0, n;
    struct list_node *plistNode = NULL;
    clistNode *pNodeTmp = NULL;
    void **array = NULL;
    if(list)
    {
        n = list->u32ListSize;
        array = (void **)malloc((n + 1)*sizeof (void *));
        if(!array)
            return NULL;
        ListForEach(plistNode,&list->listNode)
        {
            pNodeTmp = ListNodeToItem(plistNode, clistNode, listNode);
            array[i++] = pNodeTmp->data;
        }
        array[i] = end;    
    }
    return array;
}
//cList.h
#ifndef _COMMON_LIST_H
#define _COMMON_LIST_H

#include "list.h"

typedef struct clistManager{
    struct list_node listNode;
    unsigned int u32ListSize;
} *clist;

typedef struct {
    struct list_node listNode;
    void *data;
} clistNode;

clist List_push(clist list, void *x);
clist List_list(void *x, ...);
clist List_append(clist list, clist tail);
clist List_copy(clist list);
clist List_pop(clist list, void **x);
clist List_reverse(clist list);
int List_length(clist list);
void List_free(clist *plist);
void List_map(clist list, void apply(void **x,int index, void *cl), void *cl);
void **List_toArray(clist list, void *end);


#endif

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值