同单链表相似,循环链表中的每个元素也包含两个部分:一个数据域指针和一个指向后继元素的next指针。
数据结构CListElmt代表循环链表中的单独元素。该结构体拥有两个成员,如上面所述。
数据结构CList代表循环链表。这个结构体同单链表相似,但它不包含tail成员。
示例1:循环链表抽象数据类型的头文件
/*CList.h*/
#ifndef CLIST_H
#define CLIST_H
#include <stdio.h>
/*定义循环链表中元素的数据结构*/
typedef struct CListElmt_
{
void *data;
struct CListElmt_ *next;
} CListElmt;
/*定义循环链表的数据结构*/
typedef struct CList_
{
int size;
int (*match)(const void *key1,const void *key2);
void (*destroy)(void *data);
CListElmt *head;
} CList;
/*Public Interface*/
void clist_init(CList *list,void (*destroy)(void *data));
void clist_destroy(Clist *list);
int clist_ins_next(CList *list,CListElmt *element,const void *data);
int clist_rem_next(CList *list,CListElmt *element,void **data);
#define clist_size(list)((list)->size)
#define clist_head(list)((list)->head)
#define clist_data(element)((element)->data)
#define clist_next(element)((element)->next)
#endif // CLIST_H
接口定义的相关描述,请参阅循环链表接口定义
示例2:循环链表抽象数据类型的实现
/*clist.c*/
#include <stdio.h>
#include <string.h>
#include "clist.h"
/*clist_init 初始化循环链表*/
void clist_init(Clist *list,void (*destroy)(void *data))
{
list->size = 0;
list->destroy = destroy;
list->head = NULL;
return ;
}
/*clist_destroy 销毁循环链表*/
void clist_destroy(CList *list)
{
void *data;
/*移除所有元素*/
while(clist_size(list)>0)
{
if(clist_rem_next(clist,element,void **data) == 0
&& list->destroy != NULL)
{
/*调用自定义函数释放动态分配的数据空间*/
list->destroy(data);
}
}
/*链表不允许再有任何操作,清空链表结构*/
memset(list,0,sizeof(CList));
return ;
}
/*clist_ins_next 向循环链表中插入元素*/
int clist_ins_next(CList *list,CListElmt *element,const void *data)
{
CListElmt *new_element;
/*为新元素分配空间*/
if((new_element=(CListElmt *)malloc(sizeof(CListElmt)))==NULL)
return -1;
/*向链表中插入元素*/
new_element->data = (void *)data;
if(clist_size(list)==0)
{
/*当链表为空时的插入操作*/
new_element->next = new_element; /*元素的next指针指向元素本身*/
list->head = new_element; /*链表头指针指向插入元素*/
}
else
{
/*链表非空时的插入操作*/
new_element->next = element->next;
element->next =new_element;
}
/*变更链表的元素数量*/
list->size++;
return 0;
}
/*clist_rem_next 移除链表中的元素*/
int clist_rem_next(CList *list,CListElmt *element,void **data)
{
CListElmt *old_element;
/*空链表不允许有移除操作*/
if(clist_size(list)==0)
return -1;
/*从链表中移除元素*/
*data = element->next->data;
if(element->next == element) /*链表中只有一个元素*/
{
/*移除最后一个元素的操作*/
old_element = element->next;
list->head = NULL;
}
else
{
/*移除非最后一个元素的操作*/
old_element=element->next;
element->next=element->next->next;
if(old_element == clist_head(list)) /*被移除元素位于头部*/
list->head = old_element->next;
}
/*释放空间*/
free(old_element);
/*变更链表中元素的数量*/
list->size--;
return 0;
}