博客中所有源代码地址:Github托管项目地址
循环链表的介绍
循环链表是另一种形式的链表,它提供了更为灵活的遍历链表元素的能力,循环链表可以是单向的也可以是反向的,胆区分一个链表是不是循环链表只需要看它有没有尾部元素即可。在循环链表中,最后一个元素的next指针会指向头指针而不会设置为NULL。在双向链表中,头元素指针prev指针则指向最后一个元素,这可以让循环链表中的每个元素可以随意变化成为头元素或者尾元素。
定义头文件:clist.h
#ifndef CLIST_H #define CLIST_H #include <stdlib.h> typedef struct CListElmt { void *data; struct CListElmt *next }CListElmt; typedef struct CList { int size; int (*math)(const void *key1, const void *key2); void (*destory)(void *data); CListElmt *head; }CList; /* Public interface */ void clist_init(CList *list, void (*destory)(void *data)); void clist_destory(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
功能实现与分析:
1.clist_list操作用来初始化一个循环链表以便稍后能给个执行其他操作,初始化过程与非循环链表一样。
2.clist_destory用来销毁一个循环链表。总的来说,该操作意味着将以除链表中所有的元素。
3.clist_ins_next用来将新元素插入循环链表中参数element所指定的元素之后。
4.clist_rem_next将参数element所指定的元素的后继元素从链表中移除。
5.clist_size, clist_head,clist_data,clist_next是为了实现链表中一些简单的操作。
#include <stdlib.h> #include <string.h> #include "clist.h" void clist_init(Clist *list, void (*destory)(void *data)) { list->size = 0; list->head = NULL; list->destory = destory; return ; } void clist_destory(Clist *list) { void *data; while (clist_size(list) > 0) { if (clist_rem_next(list, list->head, (void**)&data) == 0 && list->destory != NULL) { list->destory(data); } } meset(list, 0, sizeof(Clist)); return ; } 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; list->head = new_element; } else { new_element->next = element->next; element->next = new_element; } list->size++; return 0; } 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; }