循环链表
特点:表中最后一个结点的指针域指向头结点,整个链表形成一个环。 既然是环的话,那就不难想象,从表中任意一个结点出发都可以找到表中其他结点。
一、循环单链表
仍旧使用该例子,我们要如何存储用循环单链表实现它呢?
id | name | description |
---|
1 | 史强 | 最强辅助 | 2 | 章北海 | 我不需要钢印,我是自己思想的主人 | 3 | 罗辑 | 人类不感谢罗辑 | 4 | 维德 | 失去人性,失去很多。失去兽性,失去一切 |
循环单链表与单链表唯一的区别就是多了一个由尾结点指向头结点的指针。 所以循环链表的操作与单链表基本一致 唯一的差别就是循环的条件不是p 或p->next 是否为空,而是它们是否等于头指针(p==L 或p->next==L )。
循环单链表示例图(含头结点): 循环单链表逻辑图(含头结点):
1、循环单链表定义
步骤一:声明数据元素类型
typedef struct{
int id;
char name[100];
char description[200];
}ElemType;
步骤二:声明结点
typedef struct CNode{
ElemType data;
struct CNode *next;
}CNode,*CLinkList;
2、循环单链表操作
与单链表相比,循环单链表有两处操作与单链表不同。 一是:尾结点的指针域指向头结点 二是:遍历时,条件变成了p->next 是否为头指针 这里只详细展示两个具体操作
初始化表。构造一个空表。
int InitList_CLink(CLinkList *L){
*L=(CLinkList)malloc(sizeof(CNode));
if (!(*L)) return FALSE;
(*L)->next=(*L);
return TRUE;
}
空表逻辑图:
求表长
int Length_CLink(CLinkList L){
int i=0;
CNode *s=L;
while (s->next!=L){
s=s->next;
i++;
}
return i;
}
3、含尾指针的循环单链表
有时候在循环单链表中设立尾指针而不设头指针,可以时有些操作简化。 比如合并两个循环单链表时
二、循环双链表
循环双链表的逻辑图(含头结点):
1、循环双链表定义
步骤一:声明数据元素类型
typedef struct{
int id;
char name[100];
char description[200];
}ElemType;
步骤二:声明结点
typedef struct CDNode{
ElemType data;
struct CDNode *prior;
struct CDNode *next;
}CDNode,*CDLinkList;
2、循环双链表操作
循环双链表与循环单链表唯一的区别就是多了一个指向前驱的指针。 所以循环双链表的操作与循环单链表也基本一致 就是对结点操作时,需要多操作一步,让p->prior 指向前驱结点。 这里展示相对于循环单链表有变化的操作。
初始化表。构造一个空表。
int InitList_CLink(CDLinkList *L){
*L=(CDLinkList)malloc(sizeof(CDNode));
if (!(*L)) return FALSE;
(*L)->prior=(*L);
(*L)->next=(*L);
return TRUE;
}
空表逻辑图:
根据数组创建双链表
1.头插法
int create_HeadInsert(CDLinkList *L,ElemType a[],int n){
CDNode *s;
int i;
for(i=n-1;i>=0;i--){
s=(CDLinkList)malloc(sizeof(CDNode));
s->data=a[i];
s->next=(*L)->next;
(*L)->next->prior=s;
s->prior=(*L);
(*L)->next=s;
}
}
2.尾插法
int create_TailInsert(CDLinkList *L,ElemType a[],int n){
CDNode *s,*r=(*L);
int i;
for(i=0;i<n;i++){
s=(CDLinkList)malloc(sizeof(CDNode));
s->data=a[i];
r->next=s;
s->prior=r;
r=s;
}
r->next=(*L);
}
插入操作。在表L中的第i个位置上插入指定元素e。
int ListInsert_CDLink(CDLinkList *L,int i,ElemType e){
int j=0;
CDNode *p=(*L);
CDNode *s;
while (p->next!=(*L)&&j<i-1){
p=p->next;
j++;
}
if(p==(*L)||(i-j)>1) return FALSE;
s=(CDLinkList)malloc(sizeof(CDNode));
s->data=e;
s->next=p->next;
p->next->prior=s;
s->prior=p;
p->next=s;
}
删除操作。删除表中L中第i个位置的元素,并用e返回删除的元素。
int ListDelete_CDLink(CDLinkList *L,int i,ElemType *e){
int j=0;
CDNode *p=(*L);
CDNode *q;
while (p->next!=(*L)&&j<i-1){
p=p->next;
j++;
}
if ((p->next)==(*L)||i<1) return FALSE;
q=p->next;
p->next=q->next;
q->next->prior=p;
*e=q->data;
free(q);
return TRUE;
}
三、 循环单链表完整源码
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
typedef struct{
int id;
char name[100];
char description[200];
}ElemType;
typedef struct CNode{
ElemType data;
struct CNode *next;
}CNode,*CLinkList;
int InitList_CLink(CLinkList *L){
*L=(CLinkList)malloc(sizeof(CNode));
if (!(*L)) return FALSE;
(*L)->next=(*L);
return TRUE;
}
int create_HeadInsert(CLinkList *L,ElemType a[],int n){
CNode *s;
int i;
for(i=n-1;i>=0;i--){
s=(CLinkList)malloc(sizeof(CNode));
s->data=a[i];
s->next=(*L)->next;
(*L)->next=s;
}
}
int create_TailInsert(CLinkList *L,ElemType a[],int n){
CNode *s,*r=(*L);
int i;
for(i=0;i<n;i++){
s=(CLinkList)malloc(sizeof(CNode));
s->data=a[i];
r->next=s;
r=s;
}
r->next=(*L);
}
int Length_CLink(CLinkList L){
int i=0;
CNode *s=L;
while (s->next!=L){
s=s->next;
i++;
}
return i;
}
int ListInsert_CLink(CLinkList *L,int i,ElemType e){
int j=0;
CNode *p=(*L);
CNode *s;
while (p->next!=(*L)&&j<i-1){
p=p->next;
j++;
}
if(p==(*L)||(i-j)>1) return FALSE;
s=(CLinkList)malloc(sizeof(CNode));
s->data=e;
s->next=p->next;
p->next=s;
}
int ListDelete_CLink(CLinkList *L,int i,ElemType *e){
int j=0;
CNode *p=(*L);
CNode *q;
while (p->next!=(*L)&&j<i-1){
p=p->next;
j++;
}
if ((p->next)==(*L)||i<1) return FALSE;
q=p->next;
p->next=q->next;
*e=q->data;
free(q);
return TRUE;
}
int GetElem_CList(CLinkList L,int i,ElemType *e){
CNode *p=L;
int j=0;
while (p->next!=L&&j<i){
p=p->next;
++j;
}
if(p==L||i<1) return FALSE;
*e=p->data;
return TRUE;
}
int LocateElem_CList(CLinkList L,ElemType e,int *i){
CNode *s=L;
int j=0;
while (s->next!=L){
s=s->next;
j++;
if (s->data.id==e.id){
*i=j;
return TRUE;
}
}
return FALSE;
}
void PrintList_CLink(CLinkList L){
CNode *s=L;
int i=0;
while (s->next!=L)
{
s=s->next;
i++;
printf("第%d行:id=%d,name=%s,description=%s\n",i,s->data.id,s->data.name,s->data.description);
}
}
void DestroyCList(CLinkList *L){
while((*L)->next!=(*L)) {
CNode *p=(*L)->next;
(*L)->next=p->next;
free(p);
}
}
int main(){
CLinkList L;
int i=InitList_CLink(&L);
if(i==1){
printf("初始化成功\n");
}
printf("\n");
ElemType a[4]={
{1,"史强","最强辅助"},
{2,"章北海","我不需要钢印,我是自己思想的主人"},
{3,"罗辑","人类不感谢罗辑"},
{4,"维德","失去人性,失去很多。失去兽性,失去一切"}
};
create_TailInsert(&L,a,4);
PrintList_CLink(L);
printf("\n");
ElemType e={5,"xxx","xxxxxxxxxxxxxxxxxxxx"};
ListInsert_CLink(&L,5,e);
PrintList_CLink(L);
printf("\n");
ListDelete_CLink(&L,5,&e);
PrintList_CLink(L);
printf("被删除的元素:id=%d,name=%s,description=%s\n",e.id,e.name,e.description);
printf("\n");
GetElem_CList(L,4,&e);
printf("查询到的元素:id=%d,name=%s,description=%s\n",e.id,e.name,e.description);
printf("\n");
LocateElem_CList(L,a[2],&i);
printf("查询到的位序为:%d\n",i);
printf("\n");
i=Length_CLink(L);
printf("表长为:%d\n",i);
printf("\n");
DestroyCList(&L);
PrintList_CLink(L);
}
运行结果:
初始化成功
第1行:id=1,name=史强,description=最强辅助
第2行:id=2,name=章北海,description=我不需要钢印,我是自己思想的主人
第3行:id=3,name=罗辑,description=人类不感谢罗辑
第4行:id=4,name=维德,description=失去人性,失去很多。失去兽性,失去一切
第1行:id=1,name=史强,description=最强辅助
第2行:id=2,name=章北海,description=我不需要钢印,我是自己思想的主人
第3行:id=3,name=罗辑,description=人类不感谢罗辑
第4行:id=4,name=维德,description=失去人性,失去很多。失去兽性,失去一切
第5行:id=5,name=xxx,description=xxxxxxxxxxxxxxxxxxxx
第1行:id=1,name=史强,description=最强辅助
第2行:id=2,name=章北海,description=我不需要钢印,我是自己思想的主人
第3行:id=3,name=罗辑,description=人类不感谢罗辑
第4行:id=4,name=维德,description=失去人性,失去很多。失去兽性,失去一切
被删除的元素:id=5,name=xxx,description=xxxxxxxxxxxxxxxxxxxx
查询到的元素:id=4,name=维德,description=失去人性,失去很多。失去兽性,失去一切
查询到的位序为:3
表长为:4
四、 循环双链表完整源码
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
typedef struct{
int id;
char name[100];
char description[200];
}ElemType;
typedef struct CDNode{
ElemType data;
struct CDNode *prior;
struct CDNode *next;
}CDNode,*CDLinkList;
int InitList_CDLink(CDLinkList *L){
*L=(CDLinkList)malloc(sizeof(CDNode));
if (!(*L)) return FALSE;
(*L)->prior=(*L);
(*L)->next=(*L);
return TRUE;
}
int create_HeadInsert(CDLinkList *L,ElemType a[],int n){
CDNode *s;
int i;
for(i=n-1;i>=0;i--){
s=(CDLinkList)malloc(sizeof(CDNode));
s->data=a[i];
s->next=(*L)->next;
(*L)->next->prior=s;
s->prior=(*L);
(*L)->next=s;
}
}
int create_TailInsert(CDLinkList *L,ElemType a[],int n){
CDNode *s,*r=(*L);
int i;
for(i=0;i<n;i++){
s=(CDLinkList)malloc(sizeof(CDNode));
s->data=a[i];
r->next=s;
s->prior=r;
r=s;
}
r->next=(*L);
}
int Length_CDLink(CDLinkList L){
int i=0;
CDNode *s=L;
while (s->next!=L){
s=s->next;
i++;
}
return i;
}
int ListInsert_CDLink(CDLinkList *L,int i,ElemType e){
int j=0;
CDNode *p=(*L);
CDNode *s;
while (p->next!=(*L)&&j<i-1){
p=p->next;
j++;
}
if(p==(*L)||(i-j)>1) return FALSE;
s=(CDLinkList)malloc(sizeof(CDNode));
s->data=e;
s->next=p->next;
p->next->prior=s;
s->prior=p;
p->next=s;
}
int ListDelete_CDLink(CDLinkList *L,int i,ElemType *e){
int j=0;
CDNode *p=(*L);
CDNode *q;
while (p->next!=(*L)&&j<i-1){
p=p->next;
j++;
}
if ((p->next)==(*L)||i<1) return FALSE;
q=p->next;
p->next=q->next;
q->next->prior=p;
*e=q->data;
free(q);
return TRUE;
}
int GetElem_CDList(CDLinkList L,int i,ElemType *e){
CDNode *p=L;
int j=0;
while (p->next!=L&&j<i){
p=p->next;
++j;
}
if(p==L||i<1) return FALSE;
*e=p->data;
return TRUE;
}
int LocateElem_CDList(CDLinkList L,ElemType e,int *i){
CDNode *s=L;
int j=0;
while (s->next!=L){
s=s->next;
j++;
if (s->data.id==e.id){
*i=j;
return TRUE;
}
}
return FALSE;
}
void PrintList_CDLink(CDLinkList L){
CDNode *s=L;
int i=0;
while (s->next!=L)
{
s=s->next;
i++;
printf("第%d行:id=%d,name=%s,description=%s\n",i,s->data.id,s->data.name,s->data.description);
}
}
void DestroyCDList(CDLinkList *L){
while((*L)->next!=(*L)) {
CDNode *p=(*L)->next;
(*L)->next=p->next;
free(p);
}
}
int main(){
CDLinkList L;
int i=InitList_CDLink(&L);
if(i==1){
printf("初始化成功\n");
}
printf("\n");
ElemType a[4]={
{1,"史强","最强辅助"},
{2,"章北海","我不需要钢印,我是自己思想的主人"},
{3,"罗辑","人类不感谢罗辑"},
{4,"维德","失去人性,失去很多。失去兽性,失去一切"}
};
create_TailInsert(&L,a,4);
PrintList_CDLink(L);
printf("\n");
ElemType e={5,"xxx","xxxxxxxxxxxxxxxxxxxx"};
ListInsert_CDLink(&L,5,e);
PrintList_CDLink(L);
printf("\n");
ListDelete_CDLink(&L,5,&e);
PrintList_CDLink(L);
printf("被删除的元素:id=%d,name=%s,description=%s\n",e.id,e.name,e.description);
printf("\n");
GetElem_CDList(L,4,&e);
printf("查询到的元素:id=%d,name=%s,description=%s\n",e.id,e.name,e.description);
printf("\n");
LocateElem_CDList(L,a[2],&i);
printf("查询到的位序为:%d\n",i);
printf("\n");
i=Length_CDLink(L);
printf("表长为:%d\n",i);
printf("\n");
DestroyCDList(&L);
PrintList_CDLink(L);
}
运行结果:
初始化成功
第1行:id=1,name=史强,description=最强辅助
第2行:id=2,name=章北海,description=我不需要钢印,我是自己思想的主人
第3行:id=3,name=罗辑,description=人类不感谢罗辑
第4行:id=4,name=维德,description=失去人性,失去很多。失去兽性,失去一切
第1行:id=1,name=史强,description=最强辅助
第2行:id=2,name=章北海,description=我不需要钢印,我是自己思想的主人
第3行:id=3,name=罗辑,description=人类不感谢罗辑
第4行:id=4,name=维德,description=失去人性,失去很多。失去兽性,失去一切
第5行:id=5,name=xxx,description=xxxxxxxxxxxxxxxxxxxx
第1行:id=1,name=史强,description=最强辅助
第2行:id=2,name=章北海,description=我不需要钢印,我是自己思想的主人
第3行:id=3,name=罗辑,description=人类不感谢罗辑
第4行:id=4,name=维德,description=失去人性,失去很多。失去兽性,失去一切
被删除的元素:id=5,name=xxx,description=xxxxxxxxxxxxxxxxxxxx
查询到的元素:id=4,name=维德,description=失去人性,失去很多。失去兽性,失去一切
查询到的位序为:3
表长为:4
|