一、基本思路
1.循环链表与单链表的区别
(1)初始化的时候,头结点的next指向它自己;
(2)判断条件上,由p!=NULL更换为p != *L;
(3)更新尾结点的时候,要由NULL改为*L;
二、代码如下
/*
项目名称:循环链表的建立与基本操作
编译环境:VC++ 2008
作者相关:。。。
最后修改:2019.5.31
学习目标:1.掌握循环链表的基本操作
2.利用头指针实现的循环链表
注意事项:1.测试所有功能是否正常
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int ElemType;
typedef bool Status;
//定义链表结点结构体
typedef struct Node
{
ElemType data;
struct Node *next;
}Node,*LinkList;
//函数声明
Status InitList( LinkList *L );
Status ListEmpty( LinkList L );
Status ClearList( LinkList *L );
int LengthList( LinkList L );
int LocateElem( LinkList L, ElemType e );
Status GetElem( LinkList L, int i, ElemType *e );
Status ListInsert( LinkList *L, int i, ElemType e );
void CreateListHead( LinkList *L, int n );//头插法
void CreateListTail( LinkList *L, int n );//尾插法
Status ListDelete( LinkList *L, int i, ElemType *e );
Status OutList( LinkList L );
int main()
{
LinkList L1,L2,L3;
if(InitList(&L1))
printf("L1已被初始化!\n\n");
if(ListEmpty(L1))
printf("L1为空!\n\n");
for(int i=1;i<=10;i++)
ListInsert(&L1,1,i);
OutList(L1);
printf("循环链表的长度是%d \n\n",LengthList(L1));
if(!ListEmpty(L1))
{
int k = LocateElem(L1,7);
printf("循环链表中元素7的位置是%d\n\n",k);
LocateElem(L1,11);
GetElem(L1,3,&k);
printf("循环链表中第3个元素是%d\n\n",k);
ListDelete(&L1,9,&k);
printf("删除第9个元素%d后,",k);
OutList(L1);
}
else
printf("循环链表是空的!\n\n");
ClearList(&L1);
printf("清空链表后:");
if(ListEmpty(L1))
printf("L1为空!\n\n");
CreateListHead(&L2,10);
printf("头插法创建,");
OutList(L2);
CreateListTail(&L3,10);
printf("尾插法创建,");
OutList(L3);
return 0;
}
//初始化,建立头结点,L指向此头结点
Status InitList( LinkList *L )
{
*L = (LinkList)malloc(sizeof(Node));//头结点是LinkList类型
if(!L)
return ERROR;
(*L)->next = *L;//头结点的next指向它自己
return OK;
}
Status ListEmpty( LinkList L )
{
if(L->next != L)
return FALSE;
else
return TRUE;
}
//清空链表:只保留头结点
Status ClearList( LinkList *L )
{
LinkList p,q;
p = (*L)->next;//p指向第一个结点
while(p!=*L)
{
q = p->next;
free(p);//释放p所指向结点的内存
p = q;//p再指向下一个结点
}
(*L)->next = *L;
return OK;
}
int LengthList( LinkList L )
{
LinkList p;
int count = 0;
p=L->next;//p指向第一个结点
while(p!=L)
{
++count;
p = p->next;
}
return count;
}
//返回链表中与e相等元素的位置,没有则返回0
int LocateElem( LinkList L, ElemType e )
{
if(ListEmpty(L))
{
printf("循环链表是空的!\n\n");
return ERROR;
}
LinkList p;
int i=1;
p = L->next;//p指向第一个结点
while(p!=L)
{
if(p->data == e)
return i;
else
{
p=p->next;
++i;
}
}
if(p == L)
{
printf("循环链表里与%d相等的元素不存在!\n\n",e);
return 0;
}
}
//用e返回链表中第i个数据元素的值
Status GetElem( LinkList L, int i, ElemType *e )
{
LinkList p;
int j = 1;
p = L->next;
while(p!=L&&j<i)//算法思想:工作指针后移
{
p=p->next;
++j;
}
if(p==L||j>i)
return ERROR;
*e = p->data;
return OK;
}
//在第i个元素之前插入数据e
Status ListInsert( LinkList *L, int i, ElemType e )
{
LinkList p,s;
int j = 1;
p = *L;
if( i<1 ||i>LengthList(*L)+1)
{
printf("i 的值非法!\n\n");
}
while(j<i)
{
p=p->next;
++j;
}
s=(LinkList)malloc(sizeof(Node));
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
//随机产生n个数,利用头插法完成链表的''整表创建''
void CreateListHead( LinkList *L, int n )
{
LinkList p;
*L = (LinkList)malloc(sizeof(Node));
(*L)->next = *L;
srand(time(0));//随时间产生不同的随机数种子
for(int i=0;i<n;i++)
{
p = (LinkList)malloc(sizeof(Node));
p->data = rand()%100+1;//任何数对100取余是0~99,进而取值范围是1~100
p->next = (*L)->next;
(*L)->next = p;
}
}
//随机产生n个数,利用尾插法完成链表的''整表创建''
void CreateListTail( LinkList *L, int n )
{
LinkList p,s;//p指向尾结点
*L = (LinkList)malloc(sizeof(Node));
srand(time(0));
p = *L;
for(int i=0;i<n;i++)
{
s = (LinkList)malloc(sizeof(Node));
s->data = rand()%100+1;
p->next = s;
p = s;//更新p的位置到尾结点
}
p->next = *L;
}
//删除链表中第i个数据元素
Status ListDelete( LinkList *L, int i, ElemType *e )
{
LinkList p,q;
int j=1;
p = *L;
while(p->next!=(*L)&&j<i)//p有后继结点并且j<i
{
p=p->next;
++j;
}
if(p==*L||j>i)//i的值不存在
{
return ERROR;
}
q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return OK;
}
Status OutList( LinkList L )
{
LinkList p;
p=L->next;
printf("循环链表内容如下: \n\n");
while(p!=L)
{
printf("%d ",p->data);
p=p->next;
}
printf("\n\n");
return OK;
}