C算法精解---链表(2)
前面对单链表和双链表的定义和抽象数据类型进行简单的介绍。下面介绍另外一种链表,循环链表。他提供了一种更灵活的遍历链表元素的能力,循环链表可以是单向的也可以是双向的。区分链表是循环链表的主要看他最后一个元素的next指针是不是指向的头元素。下面是以单向链表来介绍。循环链表的实现和分析:
#ifndef CLIST_H#define CLIST_H#include <stdlib.h>/*define a structure for linked CList elements */typedef struct CListElmt_{ void *data; struct CListElmt_ *next;}CListElmt;/*define a structure for linked clists */typedef struct CList_ { int size; int (*match)(const void * key1, const void * key2); void (*destroy)(void *data); CListElmt *head;}CList;/*Public Intefaces */void clist_init(CList *clist, void (*destroy)(void *data));void clist_destory(CList *clist);int clist_ins_next(CList *clist, CListElmt *element, const void *data);int clist_rem_next(CList *clist, CListElmt *element, void *data);#define clist_size(clist) ((clist) -> size)#define clist_head(clist) ((clist) -> head)#define clist_is_head(clist, element) ((element) == (clist) -> head ? 1:0)#define clist_data(element) ((element) -> data)#define clist_next(element) ((element) -> next)#endif
/*cclist.c*/#include <studio.h>#include <string.h>#include "../include/Clist.h"/*clist_init */void clist_init(List * clist, void(* destroy)(void * data)) { /* initialize the clist */ clist -> size = 0; clist -> destroy = destroy; clist -> head = NULL; return ;}/*clist_destroy */void clist_destory(List * clist) { void *data; /*Remove eah element */ while (clist_size(clist) > 0){ if (clist_rem_next(clist, clist->head, (void **) &data) == 0 && clist -> destroy != NULL){ /* Call a user-defined function to free dynamically allocated data*/ clist ->destroy(data); } } memset(clist, 0, sizeof(CList)); return;}/*clist_ins_nest */int clist_ins_next (List * clist, CListElmt * element, const void * data){ CListElmt *new_element; /* Allocate storage for the element */ if ((new_element = (CListElmt *)malloc(sizeof(CListElmt))) == NULL){ return -1; } /*insert the element into the clist */ new_element ->data =(void *)data; if (clist_size(clist) == 0){ new_element ->next = new_element; clist -> head = new_element; } else { /*Handle insertion somewhere other than at the head */ new_element ->next = element ->next; element->next = new_element; } clist->size ++; return 0; }/* clist_rem_next */int clist_rem_next(CList * clist, CListElmt * element, void * data) { CListElmt *old_element; /* do not allow the empty clist */ if (clist_size(clist) == 0){ return -1; } /*remove the element from the list */ *data = element->next->data; if (element->next == element){ old_element = element->next; clist->head = NULL; } else { old_element = element->next; if (element->next == clist->head){ clist->head = element->next->next; } element->next = element->next->next; } free(old_element); clist->size--; return 0;}