C 双向链表的实现
rlist.h代码
#ifndef __LIST_H #define __LIST_H #include <stdbool.h> #include <pthread.h> #define UT_BASE(TYPE) \ struct { \ TYPE *prev; \ TYPE *next; \ } #define listSize(p) (p->listlen) #define nodeSize(p) (p->nodelen) #define listHead(p) (p->head) #define listTail(p) (p->tail) typedef struct listNode{ struct listNode *prev; struct listNode *next; size_t size; char buf[]; }listNode; typedef struct list { unsigned long nodelen; listNode *head; listNode *tail; UT_BASE(struct list) base; pthread_mutex_t lock; }list; typedef struct listmgr { unsigned int listlen; list *head; list *tail; pthread_mutex_t lock; }listmgr; /* *date:2015-08-29 *author:zhoulin *function:create a double link list *parameter: * direct:if true,add list to head */ list *listCreate(bool direct); int listRelease(list *lt); listNode *listAddNode(list *lt,void *data,size_t size,bool direct); int listDelNode(list *lt,listNode *nd); #endif
rlist.c代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "rlist.h" static listmgr *mgr=NULL; list * listCreate(bool direct) { #ifdef INFO printf(" ****************Enter listCreate(bool =%d)****************\n",direct); #endif list *cur; if(!mgr){ mgr=(listmgr *)malloc(sizeof(*mgr)); pthread_mutex_init(&mgr->lock,NULL); mgr->listlen=0; } if(!(cur=(list *)malloc(sizeof(*cur)))) return NULL; if(!mgr->head){ pthread_mutex_lock(&mgr->lock); cur->base.prev=cur->base.next=NULL; mgr->head=mgr->tail=cur; ++mgr->listlen; pthread_mutex_unlock(&mgr->lock); } else{ if(direct){ cur->base.prev=mgr->head->base.prev; cur->base.next=mgr->head; mgr->head->base.prev=cur; mgr->head=cur; } else{ cur->base.next=mgr->tail->base.next; mgr->tail->base.next=cur; cur->base.prev=mgr->tail; mgr->tail=cur; } pthread_mutex_lock(&mgr->lock); ++mgr->listlen; cur->nodelen=0; cur->head=cur->tail=NULL; pthread_mutex_unlock(&mgr->lock); } #ifdef INFO printf(" ->add list =%p\n",cur); #endif return cur; } int listRelease(list *lt) { #ifdef INFO printf(" ****************Enter listRelease(list =%p)****************\n\n",lt); #endif if(!mgr){return 1;} if(!lt){return 1;} if(mgr->listlen<=0){return 1;} if(lt->base.prev&<->base.next){ lt->base.prev->base.next=lt->base.next; lt->base.next->base.prev=lt->base.prev; } else if(!lt->base.prev&<->base.next){ mgr->head=lt->base.next; mgr->head->base.prev=NULL; } else if(lt->base.prev&&!lt->base.next){ mgr->tail=lt->base.prev; mgr->tail->base.next=NULL; } else{ mgr->head=mgr->tail=NULL; } lt->head=lt->tail=NULL; lt->base.prev=lt->base.next=NULL; listNode *nd=lt->head; while(nd!=NULL) { listNode *nd_next=nd->next; free(nd); nd=nd_next; } free(lt); lt=NULL; pthread_mutex_lock(&mgr->lock); --mgr->listlen; pthread_mutex_unlock(&mgr->lock); return 0; } void listPrt(listmgr *mgr) { #ifdef INFO printf(" ****************Enter listPrt(listmgr =%p)****************\n",mgr); printf(" mgr->head =%p,mgr->tail =%p,mgr->listlen =%d\n",mgr->head,mgr->tail,mgr->listlen); #endif list *lt=mgr->head; while(lt!=NULL) { #ifdef INFO printf(" current list =%p,node of len=%d,prev = %p,next =%p\n",lt,lt->nodelen,lt->base.prev,lt->base.next); #endif listNode *lnd=lt->head; while(lnd!=NULL) { #ifdef INFO printf(" listNode =%p,prev = %p,next =%p\n",lnd,lnd->prev,lnd->next); #endif lnd=lnd->next; } lt=lt->base.next; } } void listDestroy(listmgr *mgr) { #ifdef INFO printf(" ****************Enter listDestroy(listmgr =%p)****************\n",mgr); #endif list *lt=mgr->head; while(lt!=NULL) { list *lt_next=lt->base.next; listNode *tmp=lt->head; #ifdef INFO printf(" ##free list = %p\n",lt); #endif while(tmp!=NULL) { listNode *t=tmp->next; #ifdef INFO printf(" ->free listNode =%p\n",tmp); #endif free(tmp); tmp=t; } free(lt); lt=lt_next; } } listNode *listAddNode(list *lt,void *data,size_t size,bool direct) { printf(" ****************listAddNode(list =%p,data=%p,size =%d,direct =%d)****************\n",lt,data,size,direct); listNode *cur=NULL; if(!lt||size<=0){return NULL;} if((cur=(listNode *)malloc(sizeof(*cur)+size))==NULL){ return NULL; } memset((char *)&cur->buf,'\0',size); cur->size=size; memcpy((char *)&cur->buf,data,size); printf(" listNode =%p,buf =%p\n",cur,cur->buf); if(!lt->head){ cur->prev=cur->next=NULL; lt->head=lt->tail=cur; } else{ if(direct){ cur->prev=NULL; cur->next=lt->head; lt->head->prev=cur; lt->head=cur; } else{ cur->next=NULL; lt->tail->next=cur; cur->prev=lt->tail; lt->tail=cur; } } pthread_mutex_lock(<->lock); ++lt->nodelen; pthread_mutex_unlock(<->lock); return cur; } int listDelNode(list *lt,listNode *nd) { if(!lt||!nd){return 1;} return 0; } int main(void) { printf("@=1\n\n"); list *a0=listCreate(true); int i=100; long x=2000; char c='A'; listNode *n1=listAddNode(a0,(char *)&i,4,true); listNode *n2=listAddNode(a0,(char *)&x,8,false); listNode *n3=listAddNode(a0,(char *)&c,1,true); printf("n1->buf =%d\n",*(int *)n1->buf); printf("n2->buf =%ld\n",*(long *)n2->buf); printf("n3->buf =%c\n",*(char *)n3->buf); listPrt(mgr); listRelease(a0); listPrt(mgr); printf("@=2 head\n\n"); list *a1=listCreate(false); list *a2=listCreate(true); listPrt(mgr); listRelease(a2); listPrt(mgr); printf("@=2 tail\n\n"); a2=listCreate(true); listPrt(mgr); listRelease(a1); listPrt(mgr); printf("@>2 \n\n"); a1=listCreate(false); list *a4=listCreate(true); list *a5=listCreate(false); list *a6=listCreate(true); listPrt(mgr); listRelease(a4); listPrt(mgr); listDestroy(mgr); return 0; }
运行结果:
[mysql@centos2 sredis]$ ./rlist @=1 ****************Enter listCreate(bool =1)**************** ->add list =0x218d060 ****************listAddNode(list =0x218d060,data=0x7ffdce89ff74,size =4,direct =1)**************** listNode =0x218d0c0,buf =0x218d0d8 ****************listAddNode(list =0x218d060,data=0x7ffdce89ff68,size =8,direct =0)**************** listNode =0x218d0f0,buf =0x218d108 ****************listAddNode(list =0x218d060,data=0x7ffdce89ff67,size =1,direct =1)**************** listNode =0x218d120,buf =0x218d138 n1->buf =100 n2->buf =2000 n3->buf =A ****************Enter listPrt(listmgr =0x218d010)**************** mgr->head =0x218d060,mgr->tail =0x218d060,mgr->listlen =1 current list =0x218d060,node of len=3,prev = (nil),next =(nil) listNode =0x218d120,prev = (nil),next =0x218d0c0 listNode =0x218d0c0,prev = 0x218d120,next =0x218d0f0 listNode =0x218d0f0,prev = 0x218d0c0,next =(nil) ****************Enter listRelease(list =0x218d060)**************** ****************Enter listPrt(listmgr =0x218d010)**************** mgr->head =(nil),mgr->tail =(nil),mgr->listlen =0 @=2 head ****************Enter listCreate(bool =0)**************** ->add list =0x218d060 ****************Enter listCreate(bool =1)**************** ->add list =0x218d150 ****************Enter listPrt(listmgr =0x218d010)**************** mgr->head =0x218d150,mgr->tail =0x218d060,mgr->listlen =2 current list =0x218d150,node of len=0,prev = (nil),next =0x218d060 current list =0x218d060,node of len=0,prev = 0x218d150,next =(nil) ****************Enter listRelease(list =0x218d150)**************** ****************Enter listPrt(listmgr =0x218d010)**************** mgr->head =0x218d060,mgr->tail =0x218d060,mgr->listlen =1 current list =0x218d060,node of len=0,prev = (nil),next =(nil) @=2 tail ****************Enter listCreate(bool =1)**************** ->add list =0x218d150 ****************Enter listPrt(listmgr =0x218d010)**************** mgr->head =0x218d150,mgr->tail =0x218d060,mgr->listlen =2 current list =0x218d150,node of len=0,prev = (nil),next =0x218d060 current list =0x218d060,node of len=0,prev = 0x218d150,next =(nil) ****************Enter listRelease(list =0x218d060)**************** ****************Enter listPrt(listmgr =0x218d010)**************** mgr->head =0x218d150,mgr->tail =0x218d150,mgr->listlen =1 current list =0x218d150,node of len=0,prev = (nil),next =(nil) @>2 ****************Enter listCreate(bool =0)**************** ->add list =0x218d060 ****************Enter listCreate(bool =1)**************** ->add list =0x218d1b0 ****************Enter listCreate(bool =0)**************** ->add list =0x218d210 ****************Enter listCreate(bool =1)**************** ->add list =0x218d270 ****************Enter listPrt(listmgr =0x218d010)**************** mgr->head =0x218d270,mgr->tail =0x218d210,mgr->listlen =5 current list =0x218d270,node of len=0,prev = (nil),next =0x218d1b0 current list =0x218d1b0,node of len=0,prev = 0x218d270,next =0x218d150 current list =0x218d150,node of len=0,prev = 0x218d1b0,next =0x218d060 current list =0x218d060,node of len=0,prev = 0x218d150,next =0x218d210 current list =0x218d210,node of len=0,prev = 0x218d060,next =(nil) ****************Enter listRelease(list =0x218d1b0)**************** ****************Enter listPrt(listmgr =0x218d010)**************** mgr->head =0x218d270,mgr->tail =0x218d210,mgr->listlen =4 current list =0x218d270,node of len=0,prev = (nil),next =0x218d150 current list =0x218d150,node of len=0,prev = 0x218d270,next =0x218d060 current list =0x218d060,node of len=0,prev = 0x218d150,next =0x218d210 current list =0x218d210,node of len=0,prev = 0x218d060,next =(nil) ****************Enter listDestroy(listmgr =0x218d010)**************** ##free list = 0x218d270 ##free list = 0x218d150 ##free list = 0x218d060 ##free list = 0x218d210