前面对单链表和双链表的定义和抽象数据类型进行简单的介绍。下面介绍另外一种链表,循环链表。他提供了一种更灵活的遍历链表元素的能力,循环链表可以是单向的也可以是双向的。区分链表是循环链表的主要看他最后一个元素的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;
}