1. 背景说明
循环链表(circular linked list),是另一种形式的链式存储结构。它的特点是表中最后一个结点的指针域指向头结点,
整个链表形成一个环。由此,从表中任一结点出发均可找到表中其他结点 。
2. 示例代码
1) status.h
/* DataStructure 预定义常量和类型头文件 */
#ifndef STATUS_H
#define STATUS_H
#define CHECK_NULL(pointer) if (!(pointer)) { \
printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_PTR); \
return NULL; \
}
#define CHECK_RET(ret) if (ret != RET_OK) { \
printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret); \
return ret; \
}
#define CHECK_VALUE(value, ERR_CODE) if (value) { \
printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_CODE); \
return ERR_CODE; \
}
#define CHECK_FALSE(value, ERR_CODE) if (!(value)) { \
printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_CODE); \
return FALSE; \
}
/* 函数结果状态码 */
#define TRUE 1 /* 返回值为真 */
#define FALSE 0 /* 返回值为假 */
#define RET_OK 0 /* 返回值正确 */
#define INFEASIABLE 2 /* 返回值未知 */
#define ERR_MEMORY 3 /* 访问内存错 */
#define ERR_NULL_PTR 4 /* 空指针错误 */
#define ERR_MEMORY_ALLOCATE 5 /* 内存分配错 */
#define ERR_NULL_STACK 6 /* 栈元素为空 */
#define ERR_PARA 7 /* 函数参数错 */
#define ERR_OPEN_FILE 8 /* 打开文件错 */
#define ERR_NULL_QUEUE 9 /* 队列为空错 */
#define ERR_FULL_QUEUE 10 /* 队列为满错 */
#define ERR_NOT_FOUND 11 /* 表项不存在 */
typedef int Status; /* Status 是函数的类型,其值是函数结果状态代码,如 RET_OK 等 */
typedef int Bollean; /* Boolean 是布尔类型,其值是 TRUE 或 FALSE */
#endif // !STATUS_H
2) cycleSingleList.h
/* 设立尾指针的单循环链表实现头文件 */
#ifndef CYCLESINGLELINKLIST_H
#define CYCLESINGLELINKLIST_H
#include "status.h"
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} *LinkList;
/* 操作结果:构造一个空的线性表 L */
Status InitList(LinkList *L);
/* 操作结果:销毁线性表 L */
Status DestroyList(LinkList *L);
/* 初始条件:线性表 L 已存在
操作结果:将 L 重置为空表 */
Status ClearList(LinkList *L);
/* 初始条件:线性表 L 已存在
操作结果:若 L 为空表,则返回 TRUE,否则返回 FALSE */
Bollean ListEmpty(LinkList L);
/* 初始条件:L 已存在
操作结果:返回 L 中数据元素个数 */
int ListLength(LinkList L);
/* 当第 i 个元素存在时,其值赋给 e 并返回 RET_OK, 否则返回 ERROR */
Status GetElem(LinkList L, int i, ElemType *e);
/* 初始条件:线性表 L 已存在,compare() 是数据元素判定函数
操作结果:返回 L 中第 1 个与 e 满足关系 compare() 的数据元素的位序
若这样的数据元素不存在,则返回值为 0 */
int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType));
/* 初始条件:线性表 L 已存在
操作结果:若 curr_e 是 L 的数据元素,且不是第一个,则用 pre_e 返回它的前驱
否则操作失败,pre_e 无定义 */
Status PriorElem(LinkList L, ElemType curr_e, ElemType *pre_e);
/* 初始条件:线性表 L 已存在
操作结果:若 curr_e 是 L 的数据元素, 且不是最后一个,则用 next_e 返回它的后继
否则操作失败,next_e 无定义 */
Status NextElem(LinkList L, ElemType curr_e, ElemType *next_e);
/* 在 L 的第 i 个位置之前插入元素 e */
Status ListInsert(int i, ElemType e, LinkList *L);
/* 删除 L 的第 i 个元素,并由 e 返回其值 */
Status ListDelete(int i, LinkList *L, ElemType *e);
/* 初始条件: L 已存在
操作结果: 依次对 L 的每个数据元素调用函数 vi()。一旦 vi() 失败,则操作失败 */
Status ListTraverse(LinkList L, void(*vi)(ElemType));
#endif // !CYCLESINGLELINKLIST_H
3) cycleSingleLink.c
/* 设立尾指针的单循环链表实现源文件 */
#include "cycleSingleLinkList.h"
#include
#include
/* 辅助函数,创建一个新的节点 */
static LinkList MakeNewLNode(ElemType e)
{
LinkList newLNode = (LinkList)malloc(sizeof(struct LNode));
CHECK_NULL(newLNode)
newLNode->data = e;
newLNode->next = NULL;
return newLNode;
}
/* 操作结果:构造一个空的线性表 L */
Status InitList(LinkList *L)
{
*L = (LinkList)malloc(sizeof(struct LNode));
CHECK_VALUE(!(*L), ERR_MEMORY_ALLOCATE)
(*L)->next = *L;
return RET_OK;
}
/* 操作结果:销毁线性表 L, *L 指的是尾指针 */
Status DestroyList(LinkList *L)
{
LinkList p = (*L)->next;
while (p != *L) {
LinkList q = p->next;
free(p);
p = q;
}
free(*L);
*L = NULL;
return RET_OK;
}
/* 初始条件:线性表 L 已存在
操作结果:将 L 重置为空表 */
Status ClearList(LinkList *L)
{
*L = (*L)->next;
LinkList p = (*L)->next;
while (p != *L) {
LinkList q = p->next;
free(p);
p = q;
}
(*L)->next = *L;
return RET_OK;
}
/* 初始条件:线性表 L 已存在
操作结果:若 L 为空表,则返回 TRUE,否则返回 FALSE */
Bollean ListEmpty(LinkList L)
{
return (L->next == L) ? TRUE : FALSE;
}
/* 初始条件:L 已存在
操作结果:返回 L 中数据元素个数 */
int ListLength(LinkList L)
{
int length = 0;
LinkList p = L->next;
while (p != L) {
++length;
p = p->next;
}
return length;
}
/* 当第 i 个元素存在时,其值赋给 e 并返回 RET_OK, 否则返回 ERROR */
Status GetElem(LinkList L, int i, ElemType *e)
{
LinkList p = L->next->next;
CHECK_VALUE((i < 1 || i > ListLength(L)), ERR_PARA)
int pos = 0;
while (pos < i - 1) {
p = p->next;
++pos;
}
*e = p->data;
return RET_OK;
}
/* 初始条件:线性表 L 已存在,compare() 是数据元素判定函数
操作结果:返回 L 中第 1 个与 e 满足关系 compare() 的数据元素的位序
若这样的数据元素不存在,则返回值为 0 */
int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{
LinkList p = L->next->next;
int pos = 0;
while (p != L->next) {
++pos;
if (compare(p->data, e)) {
return pos;
}
p = p->next;
}
return 0;
}
/* 初始条件:线性表 L 已存在
操作结果:若 curr_e 是 L 的数据元素,且不是第一个,则用 pre_e 返回它的前驱
否则操作失败,pre_e 无定义 */
Status PriorElem(LinkList L, ElemType curr_e, ElemType *pre_e)
{
LinkList p = L->next->next;
LinkList q = p->next;
while (q != L->next) {
if (q->data == curr_e) {
*pre_e = p->data;
return TRUE;
}
p = q;
q = q->next;
}
return FALSE;
}
/* 初始条件:线性表 L 已存在
操作结果:若 curr_e 是 L 的数据元素, 且不是最后一个,则用 next_e 返回它的后继
否则操作失败,next_e 无定义 */
Status NextElem(LinkList L, ElemType curr_e, ElemType *next_e)
{
LinkList p = L->next->next;
while (p != L) {
if (p->data == curr_e) {
*next_e = p->next->data;
return TRUE;
}
p = p->next;
}
return FALSE;
}
/* 在 L 的第 i 个位置之前插入元素 e */
Status ListInsert(int i, ElemType e, LinkList *L)
{
CHECK_VALUE((i < 1 || i > ListLength(*L) + 1), ERR_PARA)
LinkList p = (*L)->next;
int pos = 0;
while (pos < i - 1) {
++pos;
p = p->next;
}
LinkList newLNode = MakeNewLNode(e);
CHECK_VALUE(!newLNode, ERR_MEMORY_ALLOCATE)
newLNode->next = p->next;
p->next = newLNode;
if (p == *L) {
*L = newLNode;
}
return RET_OK;
}
/* 删除 L 的第 i 个元素,并由 e 返回其值 */
Status ListDelete(int i, LinkList *L, ElemType *e)
{
LinkList p = (*L)->next;
CHECK_VALUE((i < 1 || i > ListLength(*L)), ERR_PARA)
int pos = 0;
while (pos < i - 1) {
++pos;
p = p->next;
}
LinkList q = p->next;
p->next = q->next;
*e = q->data;
if (q == *L) {
*L = p;
}
free(q);
return RET_OK;
}
/* 初始条件: L 已存在
操作结果: 依次对 L 的每个数据元素调用函数 vi()。一旦 vi() 失败,则操作失败 */
Status ListTraverse(LinkList L, void(*vi)(ElemType))
{
LinkList p = L->next->next;
while (p != L->next) {
vi(p->data);
p = p->next;
}
return RET_OK;
}
4) main.c
/* 入口程序源文件 */
#include "cycleSingleLinkList.h"
#include
void Visit(ElemType e);
Status Compare(ElemType e1, ElemType e2);
int main(void)
{
LinkList L;
Status ret = InitList(&L);
CHECK_RET(ret)
printf("LinkList L is %s\n", (ListEmpty(L) == TRUE) ? "empty" : "not empty");
ListInsert(1, 3, &L);
ListInsert(2, 5, &L);
ElemType e;
GetElem(L, 1, &e);
printf("The length of L is %d, the value of 1th element is %d\n", ListLength(L), e);
printf("The elements in L is: ");
ListTraverse(L, Visit);
putchar('\n');
PriorElem(L, 5, &e);
printf("The previous element of 5 is %d\n", e);
NextElem(L, 3, &e);
printf("The next element of 3 is %d\n", e);
printf("LinkList L is %s\n", (ListEmpty(L) == TRUE) ? "empty" : "not empty");
ret = LocateElem(L, 5, Compare);
if (ret) {
printf("The %dth element of L is %d\n", ret, 5);
} else {
printf("The element 5 is not exist in L.\n");
}
printf("Delete the 2th element of L\n");
ret = ListDelete(2, &L, &e);
if (ret == RET_OK) {
printf("The element deleted is %d, Now the elements in L is: ", e);
ListTraverse(L, Visit);
putchar('\n');
} else {
printf("Delete element failed!\n");
}
printf("Clear L %s\n", (ClearList(&L) == RET_OK) ? "success" : "not success");
printf("Now L is %s\n", (ListEmpty(L) == TRUE) ? "empty" : "not empty");
printf("Destroy L %s\n", (DestroyList(&L) == TRUE) ? "success" : "not success");
return 0;
}
void Visit(ElemType e)
{
printf("%d ", e);
}
Status Compare(ElemType e1, ElemType e2)
{
return (e1 == e2) ? TRUE : FALSE;
}
3. 输出示例