一、循环链表的定义
将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表
二、带头结点的循环链表的判空条件
p->next 不等于头结点
在设计循环单链表时,仅设计指向终端结点的尾指针可以提高效率,此时查找开始结点和终端结点就很方便了,下面以此来实现循环单链表
三、循环单链表的基本操作
1.循环单链表的整表创建
typedef int ElemType;
typedef struct Node
{
ElemType data;
struct Node* next;
}Node, * LinkList;
void CreateCycleList(LinkList* rear,int n)
{
int data;
LinkList p,head;
(*rear) = (LinkList)malloc(sizeof(Node)); //创建头结点
head = (*rear); //记录下头结点的位置
(*rear)->next = head; //初始化头结点的后继结点指向自己
for(int i=0;i<n;i++)
{
scanf("%d",&data); //假设数据域是int类型
p = (LinkList)malloc(sizeof(Node)):
p->data = data;
p->next = head; //新结点的后继结点指向头结点
(*rear)->next = p; //尾指针指向结点的后继结点指向新结点
(*rear) = p;//更新尾指针
}
}
2.循环单链表结点的获取
/*初始条件:表已经存在*/
/*操作结果:返回第i个位置的结点*/
LinkList GetNode(LinkList rear,int i)
{
if(i==0)
return rear->next; //i等于0时可以选择返回头结点
LinkList p,head;
int j = 1;
head = rear->next; //记下头结点位置
p = head->next; //给p赋值为第一个结点
while(p!=head&&j<i) //当p等于头结点说明已经遍历完整个链表
{
p = p->next;
j++;
}
if(p==head||j>i)
return NULL;
return p;
}
3.循环链表获取表长
/*初始条件:表已经存在*/
/*操作结果:返回表长*/
int GetLength(LinkList rear)
{
int count = 0;
LinkList p,head;
head = rear->next; //记下头结点
p = head->next; //从第一个结点开始
while(rear!=head)
{
P = P->next;
count++;
}
return count;
}
4.循环单链表插入
/*初始条件:表已经存在*/
/*操作结果:在第i个结点插入结点*/
Status ListInsert(LinkList* rear,int i,ElemType e)
{
LinkList p,s;
p = GetNode((*rear),i-1);
if(p==NULL)
return false;.
s = (LinkList)malloc(sizeof(Node));
if(i>GetLength(*rear))
(*rear) = s; //如果i>表长,说明是在表尾插入元素,则尾指针要及时更新
s = (LinkList)malloc(sizeof(Node));
if (i > GetLength(*rear))
(*rear) = s;
s->data = e;
s->next = p->next; //p的后继指针赋值给s的后继指针,如果s是插入在表尾的元素,则s的后继指针就指向的了头结点
p->next = s; //p的后继指针指向s
return true;
}
5.循环单链表的删除
/*初始条件:表已经存在*/
/*操作结果:删除第i个位置上的结点,并用e回收删除结点的数据域*/
Status ListDelete(LinkList* rear, int i, ElemType* e)
{
LinkList p, s;
p = GetNode((*rear), i - 1);
if (p == NULL)
return false;
if (i == GetLength(*rear))
(*rear) = p;
s = p->next;
p->next = s->next;
*e = s->data;
free(s);
return true;
}
5.循环单链表整表删除
/*初始条件:表已经存在*/
/*操作结果:删除所有数据元素,将表重置为空表*/
void ClearList(LinkList* rear)
{
LinkList p, q, head;
head = (*rear)->next; //记下头结点位置
p = head->next; //从第一个结点开始
while (p != head) //当p等于头结点说明已经清空完毕
{
q = p;
p = p->next;
free(q);
}
(*rear) = head; //更新尾指针
(*rear)->next = head; //尾指针的后继指针指向头结点
}