导言
循环列表是链式存储结构的一种形式。它的特点从名字就可以清楚,“循环”。那么如何实现循环。
循环的实现很简单,只有表的最后一个结点的指针,不是指向NULL,而是指向了头结点,那么整个链表就能形成环。
特点:从表中任一结点出发均可以找到表中其他结点
循环列表
循环列表结构
循环链表操作和线性链表基本一致,除了算法中循环条件不是p或p->next是否为空,而是判断它们是否等于头指针。
有时候会设置尾指针,以便合并操作降低为常量级复杂度。
单循环链表实现代码
//所有定义
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define TRUE 1
#define FALSE 0
typedef int Status;//为了方便算法可用性,算法的Status可以通过这里可改
typedef char ElemType;//为了输出的可用性,数据的ElemType可以通过这里更改
#include <iostream>
using namespace std;
struct CListNode
{
ElemType elem;//数据域
struct CListNode *next;//指针域
};
typedef struct CListNode *LinkList; /* 另一种定义LinkList的方法 */
//单循环列表
Status InitList_CL(LinkList *L)
{ /* 操作结果:构造一个空的线性表L */
*L = (LinkList)malloc(sizeof(struct CListNode)); /* 产生头结点,并使L指向此头结点 */
if (!*L) /* 存储分配失败 */
exit(OVERFLOW);
(*L)->next = *L; /* 指针域指向头结点 */
return OK;
}
Status DestroyList_CL(LinkList *L)
{ /* 操作结果:销毁线性表L */
LinkList q, p = (*L)->next; /* p指向第一个结点*/
while (p != *L) /* 不等于头指针时 */
{
q = p->next;
free(p);
p = q;
}
free(*L);
*L = NULL;
return OK;
}
Status ClearList_CL(LinkList *L) /* 改变L */
{ /* 初始条件:线性表L已存在。操作结果:将L重置为空表 */
LinkList p, q;
p = (*L)->next; /* p指向第一个结点 */
while (p != *L) /* 不等于头指针时 */
{
q = p->next;
free(p);
p = q;
}
(*L)->next = *L; /* 头结点指针域指向自身 */
return OK;
}
Status ListEmpty_CL(LinkList L)
{ /* 初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
if (L->next == L) /* 空 */
return TRUE;
else
return FALSE;
}
int ListLength_CL(LinkList L)
{ /* 初始条件:L已存在。操作结果:返回L中数据元素个数 */
int i = 0;
LinkList p = L->next; /* p指向第一个结点 */
while (p != L) /* 不等于头指针时 */
{
i++;
p = p->next;
}
return i;
}
Status GetElem_CL(LinkList L, int i, ElemType *e)
{ /* 当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */
int j = 1; /* 初始化,j为计数器 */
LinkList p = L->next->next; /* p指向第一个结点 */
if (i <= 0 || i>ListLength_CL(L)) /* 第i个元素不存在 */
return ERROR;
while (j<i)
{ /* 顺指针向后查找,直到p指向第i个元素 */
p = p->next;
j++;
}
*e = p->elem; /* 取第i个元素 */
return OK;
}
int LocateElem_CL(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{ /* 初始条件:线性表L已存在,compare()是数据元素判定函数 */
/* 操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
int i = 0;
LinkList p = L->next; /* p指向第一个结点 */
while (p != L)
{
i++;
if (compare(p->elem, e)) /* 满足关系 */
return i;
p = p->next;
}
return 0;
}
Status PriorElem_CL(LinkList L, ElemType cur_e, ElemType *pre_e)
{ /* 初始条件:线性表L已存在 */
/* 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, */
/* 否则操作失败,pre_e无定义 */
LinkList q, p = L->next; /* p指向第一个结点 */
q = p->next;//第二个结点
while (q != L->next) /* p没到表尾 */
{
if (q->elem == cur_e)
{
*pre_e = p->elem;
return TRUE;
}
p = q;
q = q->next;
}
return FALSE;
}
Status NextElem_CL(LinkList L, ElemType cur_e, ElemType *next_e)
{ /* 初始条件:线性表L已存在 */
/* 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继, */
/* 否则操作失败,next_e无定义 */
LinkList p = L->next; /* p指向第一个结点 */
while (p != L) /* p没到表尾 */
{
if (p->elem == cur_e)
{
*next_e = p->next->elem;
return TRUE;
}
p = p->next;
}
return FALSE;
}
Status ListInsert(LinkList *L, int i, ElemType e) /* 算法2.4 */
{ /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L)+1 */
/* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度增加 */
LinkList p = (*L), s; /* p指向头结点 */
int j = 0;
if (i <= 0 || i>ListLength_CL(*L) + 1) /* 无法在第i个元素之前插入 */
return ERROR;
while (j < i - 1) /* 寻找第i-1个结点 */
{
p = p->next;
j++;
}
s = (LinkList)malloc(sizeof(struct CListNode)); /* 生成新结点 */
s->elem = e; /* 插入L中 */
s->next = p->next;
p->next = s;
if (p == *L) /* 改变尾结点 */
*L = s;
return OK;
}
Status ListDelete_CL(LinkList *L, int i, ElemType *e) /* 改变L */
{ /* 删除L的第i个元素,并由e返回其值 */
LinkList p = (*L)->next, q; /* p指向头结点 */
int j = 0;
if (i <= 0 || i>ListLength_CL(*L)) /* 第i个元素不存在 */
return ERROR;
while (j < i - 1) /* 寻找第i-1个结点 */
{
p = p->next;
j++;
}
q = p->next; /* q指向待删除结点 */
p->next = q->next;
*e = q->elem;
if (*L == q) /* 删除的是表尾元素 */
*L = p;
free(q); /* 释放待删除结点 */
return OK;
}
Status ListTraverse_CL(LinkList L, void(*vi)(ElemType))
{ /* 初始条件:L已存在。操作结果:依次对L的每个数据元素调用函数vi()。一旦vi()失败,则操作失败 */
LinkList p = L->next->next;//表头
while (p != L->next)
{
vi(p->elem);
p = p->next;
}
return OK;
}
Status compare(ElemType c1, ElemType c2)
{
if (c1 == c2)
return TRUE;
else
return FALSE;
}
void visit(ElemType c)
{
cout << c <<" ";
}
int main()
{
//本程序说明,是在VS2013中运行的,若是其他地方无法运行,建议修改代码
//程序声明
cout << "***************************************************************************" << endl;
cout << " 《数据结构》<C语言版本>严蔚敏 吴伟名 编著 " << endl;
cout << " 编写年月2016年3月 " << endl;
cout << " 编写者:YuYunTan " << endl;
cout << " 单循环链表 " << endl;
cout << "***************************************************************************" << endl;
CListNode *A;
//初始化A
InitList_CL(&A);
ListInsert(&A, 1, 'A');
ListInsert(&A, 1, 'B');
ListInsert(&A, 1, 'C');
ListInsert(&A, 1, 'D');
cout << " CList_A = < ";
ListTraverse_CL(A, visit);
cout << " >" << endl;
ElemType a,e,pa,na;
GetElem_CL(A,2,&a);
cout << "第二个元素为:" << a << endl;
PriorElem_CL(A, a, &pa);
cout << a << "的前继结点为:"<< pa << endl;
NextElem_CL(A, a, &na);
cout << a << "的后继结点为:" << na << endl;
//表置空
ClearList_CL(&A);
cout << " ClearList_CL(A);A= < ";
ListTraverse_CL(A, visit);
cout << " >" << endl;
//表销毁
DestroyList_CL(&A);
cout << " 已销毁" << endl;
system("pause");
return 0;
}