通用链表,队列的实现

来源:互联网 发布:youcam摄像头软件 编辑:程序博客网 时间:2024/05/17 23:53

通用链表

节点定义:

#define ADD_SUCCESS 0#define ADD_FAIL -1#define DELETE_SUCCESS 0#define SELETE_FAIL -1#define CANFIND 1#define NOTFIND 0typedef struct cl_link_node cl_link_node;typedef struct cl_link cl_link;/** * 链表节点,其他结构体需要使用链表数据结构,只需包含此节点 * @return */typedef struct cl_link_node{    cl_link_node* next;    cl_link_node* prev;}cl_link_node;

节点包含两个指针,next和prev分别表示前一个和后一个节点

链表对象:

/** * 通用链表对象,也可以作为队列使用 * @return */typedef struct cl_link{    pthread_mutex_t     cl_link_mutex;  //链表锁    cl_link_node        cl_link_head;   //链表头    cl_link_node        cl_link_tail;   //链表尾    int                 sum;            //节点数}cl_link;

提供的接口:

//根据节点获取node地址,借鉴linux内核链表实现技巧#define cl_link_get_node(aim, type, node)      \    ((cl_link_node *) ((u_char *) aim + offsetof(type, node)))//根据node获取节点地址,借鉴linux内核链表实现技巧#define cl_link_get_data(aim, type, node)      \    ((type *) ((u_char *) aim - offsetof(type, node)))/** * 创建一个链表对象 * @return 链表对象地址 */cl_link* cl_link_create();/** * 链表的压栈操作 * @param  link 链表对象 * @param  node 新节点 * @return      压栈状态 */int cl_link_push(cl_link* link, void* node);/** * 链表的出栈操作 * @param link 链表对象 */void* cl_link_pop(cl_link* link);/** * 对每个节点进行操作 * @param link    链表对象 * @param res     返回值 * @param handler 处理函数 */void cl_link_each(cl_link* link, void* res[], void* (*handler)(void* node));/** * 队尾添加元素 * @param  link 队列对象 * @param  node 新节点 * @return      添加状态 */int cl_link_add_back(cl_link* link, void* node);/** * 队头获取元素 * @param  link 队列对象 * @return      取得的元素 */void* cl_link_get_front(cl_link* link);/** * 根据key查找节点 * @param link      链表对象 * @param key       关键字 * @param condition 条件 */void* cl_link_find(cl_link* link, void* key, int (*condition)(void* node, void* key));

具体实现:

#include "cl_link.h"/** * 创建一个链表对象 * @return 链表对象地址 */cl_link* cl_link_create(){    cl_link* link = malloc(sizeof(cl_link));    if(link == NULL){        write(STDERR_FILENO, "malloc error", sizeof("malloc error"));        return NULL;    }    pthread_mutex_init(&(link->cl_link_mutex), NULL);    pthread_mutex_lock(&(link->cl_link_mutex));    link->cl_link_head.next = &(link->cl_link_tail);    link->cl_link_head.prev = &(link->cl_link_tail);    link->cl_link_tail.next = &(link->cl_link_head);    link->cl_link_tail.prev = &(link->cl_link_head);    link->sum = 0;    pthread_mutex_unlock(&(link->cl_link_mutex));    return link;}/** * 链表的压栈操作 * @param  link 链表对象 * @param  node 新节点 * @return      压栈状态 */int cl_link_push(cl_link* link, void* node){    cl_link_node* new_node = (cl_link_node*)node;    pthread_mutex_lock(&(link->cl_link_mutex));    if(link)    {        new_node->next = link->cl_link_head.next;        link->cl_link_head.next->prev = new_node;        link->cl_link_head.next = new_node;        new_node->prev = &(link->cl_link_head);        link->sum++;        pthread_mutex_unlock(&(link->cl_link_mutex));        return ADD_SUCCESS;    }else{        pthread_mutex_unlock(&(link->cl_link_mutex));        return ADD_FAIL;    }}/** * 链表的出栈操作 * @param link 链表对象 */void* cl_link_pop(cl_link* link){    pthread_mutex_lock(&(link->cl_link_mutex));    if(link->sum){        cl_link_node* aim = link->cl_link_head.next;        link->cl_link_head.next = aim->next;        aim->next->prev = &(link->cl_link_head);        link->sum--;        pthread_mutex_unlock(&(link->cl_link_mutex));        return aim;    }else{        pthread_mutex_unlock(&(link->cl_link_mutex));        return NULL;    }}/** * 对每个节点进行操作 * @param link    链表对象 * @param res     返回值 * @param handler 处理函数 */void cl_link_each(cl_link* link, void* res[], void* (*handler)(void* node)){    pthread_mutex_lock(&(link->cl_link_mutex));    int n = link->sum;    void* r;    cl_link_node* p = link->cl_link_head.next;    cl_link_node* todo = p;    while(n)    {        todo = p;        p = p->next;        r = handler(todo);        if(res != NULL)        {            res[link->sum-n] = r;        }        n--;    }    pthread_mutex_unlock(&(link->cl_link_mutex));}/** * 队尾添加元素 * @param  link 队列对象 * @param  node 新节点 * @return      添加状态 */int cl_link_add_back(cl_link* link, void* node){    cl_link_node* new_node = (cl_link_node*)node;    pthread_mutex_lock(&(link->cl_link_mutex));    if(link)    {        new_node->next = &(link->cl_link_tail);        new_node->prev = link->cl_link_tail.prev;        link->cl_link_tail.prev->next = new_node;        link->cl_link_tail.prev = new_node;        link->sum++;        pthread_mutex_unlock(&(link->cl_link_mutex));        return ADD_SUCCESS;    }else{        pthread_mutex_unlock(&(link->cl_link_mutex));        return ADD_FAIL;    }}/** * 队头获取元素 * @param  link 队列对象 * @return      取得的元素 */void* cl_link_get_front(cl_link* link){    return cl_link_pop(link);}/** * 根据key查找节点 * @param link      链表对象 * @param key       关键字 * @param condition 条件 */void* cl_link_find(cl_link* link, void* key, int (*condition)(void* node, void* key)){    pthread_mutex_lock(&(link->cl_link_mutex));    int n = link->sum;    cl_link_node* p = link->cl_link_head.next;    while(n)    {        if(condition(p, key) == CANFIND)        {            pthread_mutex_unlock(&(link->cl_link_mutex));            return p;        }        p = p->next;        n--;    }    pthread_mutex_unlock(&(link->cl_link_mutex));    return NULL;}

测试代码:

#include "../cl_link.h"#include <stdio.h>#include <stdlib.h>typedef struct test{    int n;    cl_link_node node;}test;void* handler(void *arg){    test* t = cl_link_get_data(arg, test, node);    printf("%p\n",t );    free(t);    int* r = malloc(sizeof(int));    *r = rand()%10;    // printf("%d\n", cl_link_get_data(arg, test, node)->n);    return r;}int condition(void* node, void* key){    test* t = cl_link_get_data(node, test, node);    if(t->n == (int)key)        return CANFIND;    else        return NOTFIND;}int main(){    void* res[10];    cl_link* link = cl_link_create();    for(int i=0; i<10; i++){        test* a = malloc(sizeof(test));        printf("%p\n",a );        a->n = i;        cl_link_add_back(link, cl_link_get_node(a,test,node));        // if( i == 9){        //     cl_link_get_front(link);        // }    }    test* t = cl_link_find(link, (void *)5, condition);    if(t != NULL)    printf("%d\n", cl_link_get_data(t,test,node)->n);    cl_link_each(link, res, handler);    return 0;}
原创粉丝点击