循环链表(CircularLinked List)是另一种形式的链式存储结构。其特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。由此,从表中任一结点出发均可找到表中其他结点。
循环单链表的C语言实现
头文件
#include<stdlib.h>
#include<stdio.h>
//结果函数状态代码
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define MAXSIZE 100 //顺序表可能达到的最大长度
typedef int Status; // Status--函数的类型,其值是函数结果的状态代码
typedef char ElemType;
typedef struct LNode //声明节点类型和指向节点的指针类型
{
ElemType data; //节点的数据域
struct LNode *next; //节点的指针域
}Lnode, *LinkList; //LinkList为指向结构体Lnode的指针类型
初始化循环链表,R为尾指针
Status Init_LoopList(LinkList R) //初始化循环链表,R为尾指针
{
R = (LinkList)malloc(sizeof(Lnode)); //分配内存空间
R->next = R; //
return OK;
}
判断循环链表是否为空
Status IsEmpty_LoopList(LinkList R) //判断循环链表是否为空
{
if(R->next->next == R) return 1; //空返回 1
else return 0; //非空返回0
}
销毁循环链表
Status Destory_LoopList(LinkList R) //销毁循环链表
{
Lnode *p, *q;
q = R->next;
while (R != p)
{
p = q;
q = q->next;
printf("%c,",p->data);
free(p);
}
printf("销毁成功!!\n");
return OK;
}
清空单链表
Status Clear_LoopList(LinkList R) //清空单链表
{
Lnode *p, *q;
p = R->next->next;
while(p!=R->next)
{
q = p;
p = p->next;
free(q);
}
R->next->next = R;
printf("清空成功!\n");
return OK;
}
输出显示循环链表
void Show_LoopList(LinkList R) //输出显示循环链表
{
Lnode *p;
p = R->next->next; //p指向第一个节点
while(p!=R->next) //遍历单链表
{
printf("%c,",p->data);
p = p->next;
}
printf("\n");
}
求循环链表表长
int Length_LoopList(LinkList R) //求循环链表表长
{
Lnode *p;
int i=0;
p = R->next->next; //p指向第一个节点
while(p!=R->next)
{
i++;
p = p->next;
}
return i;
}
获取链表第 i 个位置的元素,放入e中
Status GetElem(LinkList R, int i, ElemType *e)
{
Lnode *p;
int j = 1;
p = R->next->next; //p指向第一个节点
while(p!=R->next && j<i)
{
p = p->next;
j++;
}
if(p==R->next && j>i) return ERROR; //第i个元素不存在,位置非法
*e = p->data;
return OK;
}
按值查找,返回地址或位置, num存放位置, p存放地址
Status LocateElem(LinkList R, ElemType e, int *num, Lnode *p)
{
int j = 1;
p = R->next->next; //p指向第一个节点
while(p!=R->next && e!=p->data)
{
p = p->next;
j++;
}
if(p!=R->next)
{
*num = j;
printf("%c\n",p->data);
return OK;
}
else return ERROR;
}
插入,在第i个节点前插入值为e的新节点
Status LoopList_Insert(LinkList R, int i, ElemType e)
{
Lnode *p;
Lnode *s = (LinkList)malloc(sizeof(Lnode));
p = R->next->next;
int j = 1;
while(p!=R->next && j<i-1)
{
p = p->next;
j++;
}
if(p==R->next || j>i-1) return ERROR;
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
删除第i个节点,利用e保存删除结点数据
Status LoopList_Delete(LinkList R, int i, ElemType *e)
{
Lnode *p = R->next->next;
int j = 1;
while(p!=R->next && j<i-1)
{
p = p->next;
j++;
}
if(p==R->next || j>i-1) return ERROR;
Lnode *q = p->next; //临时保存被删除节点的地址以备释放
p->next = q->next; //改变 i-1节点的指针域,使其指向 i+1
*e = q->data; //保存删除节点的数据域
printf("删除成功, %c\n", *e);
free(q); //释放删除结点的空间
printf("%c所在地址为%d\n",*e, &e);
return OK;
}
循环链表的创建----尾插法
LinkList Creat_LoopList_Tail(int n, ElemType e)
{
LinkList R;
R = (LinkList)malloc(sizeof(Lnode));
R->next = R; //创建带头结点的单链表
Lnode *r = R; //尾指针r指向尾结点
int i;
for(i=0;i<n;i++)
{
Lnode *p = (LinkList)malloc(sizeof(Lnode)); //生成新节点
p->data = e; //产生新元素
p->next = R;
r->next = p; //插入到表尾
e++;
r = p; //r指向新的尾结点
}
return r; //返回尾节点
}
合并两个循环链表
LinkList Merge_two_LoopList(LinkList R1, LinkList R2)
{
Lnode *p = R1->next; //存R1表头节点
R1->next = R2->next->next; //R2表头接到R1表尾;
free(R2->next); //释放R2表头节点;
R2->next = p; //修改指针,R2表尾指向R1表头;
return R2;
}
主函数
int main()
{
Status Init_LoopList(LinkList R); //初始化循环链表,R为尾指针
Status IsEmpty_LoopList(LinkList R); //判断循环链表是否为空
Status Destory_LoopList(LinkList R); //销毁循环链表
Status Clear_LoopList(LinkList R); //清空单链表
void Show_LoopList(LinkList R); //输出显示循环链表
int Length_LoopList(LinkList R); //求循环链表表长
Status GetElem(LinkList R, int i, ElemType *e); //获取链表第 i 个位置的元素,放入e中
Status LocateElem(LinkList R, ElemType e, int *num, Lnode *p); //按值查找,返回地址或位置, num存放位置, p存放地址
Status LoopList_Insert(LinkList R, int i, ElemType e); //插入,在第i个节点前插入值为e的新节点
Status LoopList_Delete(LinkList R, int i, ElemType *e); //删除第i个节点,利用e保存删除结点数据
LinkList Creat_LoopList_Tail(int n, ElemType e); //循环链表的创建----尾插法
LinkList Merge_two_LoopList(LinkList R1, LinkList R2); //合并两个循环链表
LinkList R, R1, R2;
Lnode *p;
int n = 8, i = 5, loc;
Init_LoopList(R);
R = Creat_LoopList_Tail(n, 'a'); //尾插法创建循环链表
if(!IsEmpty_LoopList(R)) //判断链表是否为空
{
printf("非空\n");
}
else printf("空\n");
Show_LoopList(R);
printf("链表表长为:%d\n", Length_LoopList(R));
printf("表尾元素为:%c\n",R->data);
ElemType e, e1;
int a = LoopList_Delete(R, i, &e);
if(a) printf("删除成功\n");
printf("删除第%d个节点的值为:%c\n", i, e);
Show_LoopList(R);
LoopList_Insert(R, i, e);
Show_LoopList(R);
GetElem(R, i, &e1);
printf("第%d个节点的值为:%c\n", i, e1);
LocateElem(R, e, &loc, &p);
printf("%c所在节点的位置为:%d,地址为%d\n", e, loc, &p);
Init_LoopList(R1);Init_LoopList(R2);
R1 = Creat_LoopList_Tail(n, 'i');
Show_LoopList(R1);
R2 = Merge_two_LoopList(R, R1); //合并两个循环链表
Show_LoopList(R2);
}