以下是“带头节点的、双向循环链表”的简单实现。
1. 用c语言实现的版本
#include<stdio.h> /* EOF(=^Z或F6),NULL */ #include<math.h> /* floor(),ceil(),abs() */ #include<stdlib.h> /* 申请和释放内存 */ #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */ typedef int ElemType; typedef struct DuLNode { ElemType data; struct DuLNode *prior, *next; }DuLNode, *DuLinkList; /* 双链循环线性表的基本操作(14个) */ /* 初始化双向循环链表L,产生其表头结点 */ Status InitList(DuLinkList *L) { *L = (DuLinkList)malloc(sizeof(DuLNode)); if (*L) { (*L)->next = (*L)->prior = *L; return OK; } else { return OVERFLOW; } } /* 初始条件:L已存在。操作结果:返回L中数据元素个数 */ int ListLength(DuLinkList L) { int i = 0; DuLinkList p = L->next; /* p指向第一个有效结点 */ while (p != L) /* p没到表头 */ { ++i; p = p->next; } return i; } /* 在带头结点的、双向循环链表L中,返回第i个元素的位置指针(在此项操作之前,要先进行i与链表长度的比较)*/ DuLinkList GetElemP(DuLinkList L, int i) { int j; DuLinkList p = L; //L为带头结点、双向循环链表L的头结点 for (j = 1; j <= i; ++j) { p = p->next; } return p; } /* 在带头结点的、双向循环链表L中第i个位置插入元素e,i的合法值为1≤i≤表长+1 */ Status ListInsert(DuLinkList L, int i, ElemType e) { DuLinkList p, s; if (i<1 || i >ListLength(L) + 1) /* i值不合法 */ { return ERROR; } p = GetElemP(L, i - 1); /* 在L中确定第i-1个元素的位置指针p */ if (!p) /* p=NULL,即第i-1个元素不存在 */ { return ERROR; } s = (DuLinkList)malloc(sizeof(DuLNode)); if (!s) { return OVERFLOW; } s->data = e; /* 在第i-1个元素之后插入 */ s->prior = p; s->next = p->next; p->next->prior = s; p->next = s; return OK; } /* 由双链、循环、线性表L的头结点出发,正序对每个数据元素调用函数visit() */ void ListTraverse(DuLinkList L, void(*visit)(ElemType)) { DuLinkList p = L->next; /* p指向头结点 */ while (p != L) { visit(p->data); p = p->next; } printf("\n"); } /* 由双链循环线性表L的头结点出发,逆序对每个数据元素调用函数visit() */ void ListTraverseBack(DuLinkList L, void(*visit)(ElemType)) { DuLinkList p = L->prior; /* p指向尾结点 */ while (p != L) { visit(p->data); p = p->prior; } printf("\n"); } /* ListTraverse()调用的函数(类型一致) */ void vd(ElemType c) { printf("%d ", c); } /* 获取第i个元素,成功则返回OK,失败则返回ERROR */ Status GetElem(DuLinkList L, int i, ElemType *e) { int j = 1; /* j为计数器 */ DuLinkList p = L->next; /* p指向第一个有效结点 */ while (p != L && j<i) /* 顺指针向后查找,直到p指向第i个元素或p指向头结点 */ { p = p->next; ++j; } if (p == L || j > i) /* 第i个元素不存在 */ { return ERROR; } *e = p->data; /* 取第i个元素 */ return OK; } /* 删除带头结点的、双向循环链表L的第i个元素,i的合法值为1≤i≤表长+1 */ Status ListDelete(DuLinkList L, int i, ElemType *e) { DuLinkList p; if (i<1 || i>ListLength(L)) /* i值不合法 */ { return ERROR; } p = GetElemP(L, i); /* 在L中确定第i个元素的位置指针p */ if (!p || p == L) /* p=NULL,即第i个元素不存在 */ { return ERROR; } *e = p->data; p->prior->next = p->next; p->next->prior = p->prior; free(p); return OK; } /* 将L重置为空表 */ Status ClearList(DuLinkList L) { DuLinkList q, p = L->next; /* p指向第一个有效结点 */ while (p != L) /* p没到表头 */ { q = p->next; free(p); p = q; } L->next = L->prior = L; /* 头结点的两个指针域均指向自身 */ return OK; } /* 销毁双向循环链表L */ Status DestroyList(DuLinkList *L) { DuLinkList q, p = (*L)->next; /* p指向第一个有效结点 */ while (p != *L) /* p没到表头 */ { q = p->next; free(p); p = q; } free(*L); *L = NULL; return OK; } /* 若L为空表,则返回TRUE,否则返回FALSE */ Status ListEmpty(DuLinkList L) { if (L->next == L && L->prior == L) { return TRUE; } else { return FALSE; } } void main() { DuLinkList L; int i; ElemType e; Status resStatus; InitList(&L); for (i = 1; i <= 7; ++i) { ListInsert(L, i, i*10); /* 在第i个结点之前插入i*10 */ } printf("正序输出链表:"); ListTraverse(L, vd); /* 正序输出 */ printf("逆序输出链表:"); ListTraverseBack(L, vd); /* 正序输出 */ printf("链表的元素个数为%d\n", ListLength(L)); /* 获取第i个元素 */ i = 4; resStatus = GetElem(L, i, &e); if (resStatus == OK) { printf("成功获取第%d个元素,其值为:%d\n", i, e); } else { printf("未能获取,第%d个元素不存在\n", i); } //删除第i个元素 i = 3; resStatus = ListDelete(L, i, &e); if (resStatus == OK) { printf("删除第%d个元素成功,其值为:%d\n", i, e); } printf("正序输出链表:"); ListTraverse(L, vd); /* 正序输出 */ ClearList(L); /* 清空链表 */ if (ListEmpty(L)) { printf("清空后,链表为空,长度为%d.\n", ListLength(L)); } else { printf("清空后,链表非空,长度为%d,请检查!\n", ListEmpty(L), ListLength(L)); } for (i = 1; i <= 7; ++i) { ListInsert(L, i, i * 10 + i); /* 在第i个结点之前插入i*10+i */ } printf("正序输出链表:"); ListTraverse(L, vd); /* 正序输出 */ /* 销毁双向循环链表L */ DestroyList(&L); printf("销毁后,链表头指针为%0x\n", L); }
运行结果如下图所示: