文章目录[隐藏]
介绍
循环单链表是单链表的另一种形式,其结构特点链表中最后一个结点的指针域不再是结束标记,而是指向整个链表的第一个结点,从而使链表形成一个环。和单链表相同,循环链表也有带头结点结构和不带头结点结构两种,带头结点的循环单链表实现插入和删除操作较为方便。
循环单链表的基本操作
初始化
typedef int ElemType;
typedef struct LNode {//定义单链表结点类型
ElemType data;
struct LNode *next;
} LinkNode;
void InitList(LinkNode *&L) {
L = (LinkNode *) malloc(sizeof(LinkNode));//创建头结点
L->next = L;
}
头插法建立循环单链表
void CreateListF(LinkNode *&L, ElemType a[], int n) {//头插法建立循环单链表
LinkNode *s;
int i;
L = (LinkNode *) malloc(sizeof(LinkNode));//创建头结点
L->next = NULL;
for (i = 0; i < n; i++) {
s = (LinkNode *) malloc(sizeof(LinkNode));//创建新结点
s->data = a[i];
s->next = L->next; //将结点s插在原开始结点之前,头结点之后
L->next = s;
}
s = L->next;
while (s->next != NULL)//查找尾结点,由s指向它
s = s->next;
s->next = L;//尾结点next域指向头结点
}
尾插法建立循环单链表
void CreateListR(LinkNode *&L, ElemType a[], int n) {//尾插法建立循环单链表
LinkNode *s, *r;
int i;
L = (LinkNode *) malloc(sizeof(LinkNode));//创建头结点
L->next = NULL;
r = L;//r始终指向终端结点,开始时指向头结点
for (i = 0; i < n; i++) {
s = (LinkNode *) malloc(sizeof(LinkNode));//创建新结点
s->data = a[i];
r->next = s;//将结点s插入结点r之后
r = s;
}
r->next = L;//尾结点next域指向头结点
}
销毁
void DestroyList(LinkNode *&L) {
LinkNode *p = L, *q = p->next;
while (q != L) {
free(p);
p = q;
q = p->next;//pre、p同步后移一个结点
}
free(p);//此时p=L,pre指向尾结点,释放
}
判断是否空表
bool ListEmpty(LinkNode *L) {
return (L->next == L);
}
求链表长度
int ListLength(LinkNode *L) {
LinkNode *p = L;
int i = 0;
while (p->next != L) {
i++;
p = p->next;
}
return (i);
}
打印输出单链表
void PrintList(LinkNode *L) {
LinkNode *p = L->next;
while (p != L) {//p不为L,输出p结点的data域
printf("%c ", p->data);
p = p->next;
}
printf("\n");
}
将第i个元素赋值给e
bool GetElem(LinkNode *L, int i, ElemType &e) {
int j = 0;
LinkNode *p;
if (L->next != L) {//单链表不为空表时
if (i == 1) {//求第一个结点值,特殊处理
e = L->next->data;
return true;
} else {//i不为1时
p = L->next;
while (j < i - 1 && p != L) {
j++;
p = p->next;
}
if (p == L)//没有找到
return false;
else {//找到了
e = p->data;
return true;
}
}
} else//单链表为空表时
return false;
}
查找
int LocateElem(LinkNode *L, ElemType e) {
LinkNode *p = L->next;
int n = 1;
while (p != L && p->data != e) {
p = p->next;
n++;
}
if (p == L)
return 0;
else
return n;
}
插入
bool ListInsert(LinkNode *&L, int i, ElemType e) {
int j = 0;
LinkNode *p = L, *s;
if (p->next == L || i == 1) {//原单链表为空表或i=1时
s = (LinkNode *) malloc(sizeof(LinkNode));//创建新结点s
s->data = e;
s->next = p->next;//将结点s插入到结点p之后
p->next = s;
return true;
} else {
p = L->next;
while (j < i - 2 && p != L) {//找第i-1个结点
j++;
p = p->next;
}
if (p == L)//未找到第i-1个结点
return false;
else {//找到第i-1个结点p
s = (LinkNode *) malloc(sizeof(LinkNode));//创建新结点s
s->data = e;
s->next = p->next;//将结点s插入到结点p之后
p->next = s;
return true;
}
}
}
删除
bool ListDelete(LinkNode *&L, int i, ElemType &e) {
int j = 0;
LinkNode *p = L, *q;
if (p->next != L) {//原单链表不为空表时
if (i == 1) {//i==1时
q = L->next;//删除第1个结点
e = q->data;
L->next = q->next;
free(q);
return true;
} else {//i不为1时
p = L->next;
while (j < i - 2 && p != L) {//找到第i-1个结点p
j++;
p = p->next;
}
if (p == L)//未找到第i-1个结点
return false;
else {//找到第i-1个结点p
q = p->next;//q指向要删除的结点
e = q->data;
p->next = q->next;//从单链表中删除q结点
free(q);//释放q结点
return true;
}
}
} else
return false;
}
编写测试
int main(){
LinkNode *h;
ElemType e;
printf("循环单链表的基本操作如下:\n");
printf("1.初始化循环单链表\n");
InitList(h);
printf("2.采用尾插法插入a,b,c,d,e元素\n");
ListInsert(h,1,'a');
ListInsert(h,2,'b');
ListInsert(h,3,'c');
ListInsert(h,4,'d');
ListInsert(h,5,'e');
printf("3.输出循环单链表:");
PrintList(h);
printf("4.循环单链表长度%d\n",ListLength(h));
printf("5.是否为空?%s\n",ListEmpty(h)?"空":"非空");
GetElem(h,3,e);
printf("6.第三个元素为:%c\n",e);
printf("7.元素a的位置为:%d\n",LocateElem(h,'a'));
printf("8.在第四个位置上插入f元素\n");
ListInsert(h,4,'f');
printf("9.输出:");
PrintList(h);
printf("10.删除第三个元素\n");
ListDelete(h,3,e);
printf("11.输出:");
PrintList(h);
printf("12.释放");
DestroyList(h);
return 1;
}