循环链表在单向链表的基础之上作了一进步的概念延伸,循环链表让链表操作变的更加灵活,单向链表的尾结点的next链域指向其头结点,本文使用C语言实现一个通用的单向循环链表
定义一个头文件clits.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 (*match) (const void *key1, const void *key2);
void (*destroy) (void *data);
CListElmt *head;
} CList;
接着定义公共接口
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)
接下来是对应的实现文件clist.c
#include <stdlib.h>
#include <string.h>
#include "clist.h"
//初始化链表
void clist_init(CList *list, void (*destroy) (void *data))
{
list->size = 0;
list->destroy = destroy;
list->head = NULL;
return;
}
//销毁链表
void clist_destroy(CList *list)
{
void *data;
//移除每一个元素
while (clist_size(list) > 0) {
if (clist_rem_next(list, list->head, (void **)&data) == 0 && list->destroy != NULL) {
//调用一个用户调用的函数释放动态分配数据
list->destroy(data);
}
}
//现在不能进行任何操作,清除结构体作为预防
memset(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++; //插入元素后修改链表的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;
}
free(old_element); //释放已分配的抽象数据类型
list->size--; //删除元素后修改链表的size
return 0;
}
最后的测试文件test.c
/*
Copyright:wuyudong
License: as you wish
Author: wuyudong <codingwu@gmail.com>
Date: 2016-12-06
Blog: www.wuyudong.com
*/
#include <stdio.h>
#include <stdlib.h>
#include "clist.h"
//打印链表
static void print_list(const CList *list)
{
CListElmt *element;
int *data, size, i;
//显示循环链表
fprintf(stdout, "List size is %d (circling twice)\n", clist_size(list));
size = clist_size(list);
element = clist_head(list);
//重复两次遍历链表来验证是循环链表
i = 0;
while (i < size * 2) {
data = clist_data(element);
fprintf(stdout, "list[%03d]=%03d\n", (i % size), *data);
element = clist_next(element);
i++;
}
return;
}
int main(int argc, char **argv)
{
CList list;
CListElmt *element;
int *data, i;
clist_init(&list, free); //初始化链表
element = clist_head(&list); //执行一些循环链表的操作
for (i = 0; i < 10; i++) {
if ((data = (int *)malloc(sizeof(int))) == NULL)
return 1;
*data = i + 1;
if (clist_ins_next(&list, element, data) != 0)
return 1;
if (element == NULL)
element = clist_next(clist_head(&list));
else
element = clist_next(element);
}
print_list(&list);
element = clist_head(&list);
for (i = 0; i < 10; i++)
element = clist_next(element);
data = clist_data(element);
fprintf(stdout, "Circling and removing an element after the one containing " "%03d\n", *data);
if (clist_rem_next(&list, element, (void **)&data) != 0)
return 1;
free(data);
print_list(&list);
element = clist_head(&list);
for (i = 0; i < 15; i++)
element = clist_next(element);
data = clist_data(element);
fprintf(stdout, "Circling and inserting 011 after the element containing " "%03d\n", *data);
if ((data = (int *)malloc(sizeof(int))) == NULL)
return 1;
*data = 11;
if (clist_ins_next(&list, element, data) != 0)
return 1;
print_list(&list);
fprintf(stdout, "Destroying the list\n");
clist_destroy(&list); //销毁循环链表
return 0;
}

Comments