一、单向循环链表的描述
循环链表:是另一种形式的链式存储结构。其特点是表中最后一个结点的指针域指向头节点,整个链表形成一个环。
单向循环链表的操作和单链表操作基本一致,差别在于:当链表遍历时,判别当前指针p是否指向表尾结点的终止条件不同。在单链表中,判别条件一般为p!=NULL或p->next!=NULL,而单向循环链表的判别条件为p!=L或p->next!=L。
二、单向循环链表存储结构
typedef int ElemType; //重定义数据域的数据类型
typedef struct LNode //定义单链表存储结构
{
ElemType data; //结点的数据域
struct LNode *next;//结点的指针域
}*LinkList; //LinkList为指向结构体LNode的指针类型
三、单向循环链表的操作
3.1 循环链表创建
LinkList Request_space() //在堆区申请一个结点空间
{
LinkList node=(LinkList)malloc(sizeof(struct LNode));
if(NULL==node)
return NULL;
node->data=0;
node->next=node;
return node;
}
3.2 循环链表遍历
int Output(LinkList L_list) //实现输出
{
if(NULL==L_list)
return -1;
LinkList p=L_list;
do
{
printf("%d ",p->data);
p=p->next;
}while(p!=L_list);
puts("");
return 0;
}
3.3 循环链表头插
LinkList insert_head(LinkList L_list,ElemType value) //实现头插
{
LinkList node=Request_space();
if(NULL==node)
return L_list;
if(NULL==L_list)
{
L_list=node;
node->data=value;
}
else
{
node->next=L_list->next;
L_list->next=node;
node->data=L_list->data;
L_list->data=value;
}
return L_list;
}
3.4 循环链表尾插
LinkList insert_rear(LinkList L_list,ElemType value) //实现尾插
{
LinkList node=Request_space();
node->data=value;
if(NULL==L_list)
L_list=node;
else
{
LinkList rear=L_list;
while(rear->next!=L_list)
rear=rear->next;
rear->next=node;
node->next=L_list;
}
return L_list;
}
3.5 循环链表头删
LinkList delete_head(LinkList L_list) //实现头删
{
if(NULL==L_list)
return NULL;
if(L_list->next==L_list)
{
free(L_list);
L_list=NULL;
}
else
{
LinkList p=L_list->next;
L_list->data=p->data;
L_list->next=p->next;
free(p);
p=NULL;
}
return L_list;
}
3.6 循环链表尾删
LinkList delete_rear(LinkList L_list) //实现尾删
{
if(NULL==L_list)
return NULL;
if(L_list->next==L_list)
{
free(L_list);
L_list=NULL;
}
else
{
LinkList rear=L_list;
while(rear->next->next!=L_list)
rear=rear->next;
free(rear->next);
rear->next=L_list;
}
return L_list;
}
3.7 循环链表解决约瑟夫环问题
int Joseph_loop(LinkList L_list,int n,int m) //单向循环链表实现约瑟夫环
{
LinkList p=L_list;
for(int i=0;i<n;i++)
{
for(int j=0;j<m-2;j++)
{
p=p->next;
}
LinkList q=p->next;
p->next=q->next;
printf("%d ",q->data);
free(q);
q=NULL;
p=p->next;
}
return 0;
}
四、多文件编辑实现单向循环链表操作
头文件 head.h
#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef int ElemType; //重定义数据域的数据类型
typedef struct LNode //定义单链表存储结构
{
ElemType data;
struct LNode *next;
}*LinkList;
LinkList Request_space(); //在堆区申请一个结点空间
int Output(LinkList L_list); //实现输出
LinkList insert_head(LinkList L_list,ElemType value); //实现头插
LinkList insert_rear(LinkList L_list,ElemType value); //实现尾插
LinkList delete_head(LinkList L_list); //实现头删
LinkList delete_rear(LinkList L_list); //实现尾删
int Joseph_loop(LinkList L_list,int n,int m); //单向循环链表实现约瑟夫环
#endif
自定义函数 fun.c
#include "head.h"
LinkList Request_space() //在堆区申请一个结点空间
{
LinkList node=(LinkList)malloc(sizeof(struct LNode));
if(NULL==node)
return NULL;
node->data=0;
node->next=node;
return node;
}
int Output(LinkList L_list) //实现输出
{
if(NULL==L_list)
return -1;
LinkList p=L_list;
do
{
printf("%d ",p->data);
p=p->next;
}while(p!=L_list);
puts("");
return 0;
}
LinkList insert_head(LinkList L_list,ElemType value) //实现头插
{
LinkList node=Request_space();
if(NULL==node)
return L_list;
if(NULL==L_list)
{
L_list=node;
node->data=value;
}
else
{
node->next=L_list->next;
L_list->next=node;
node->data=L_list->data;
L_list->data=value;
}
return L_list;
}
LinkList insert_rear(LinkList L_list,ElemType value) //实现尾插
{
LinkList node=Request_space();
node->data=value;
if(NULL==L_list)
L_list=node;
else
{
LinkList rear=L_list;
while(rear->next!=L_list)
rear=rear->next;
rear->next=node;
node->next=L_list;
}
return L_list;
}
LinkList delete_head(LinkList L_list) //实现头删
{
if(NULL==L_list)
return NULL;
if(L_list->next==L_list)
{
free(L_list);
L_list=NULL;
}
else
{
LinkList p=L_list->next;
L_list->data=p->data;
L_list->next=p->next;
free(p);
p=NULL;
}
return L_list;
}
LinkList delete_rear(LinkList L_list) //实现尾删
{
if(NULL==L_list)
return NULL;
if(L_list->next==L_list)
{
free(L_list);
L_list=NULL;
}
else
{
LinkList rear=L_list;
while(rear->next->next!=L_list)
rear=rear->next;
free(rear->next);
rear->next=L_list;
}
return L_list;
}
int Joseph_loop(LinkList L_list,int n,int m) //单向循环链表实现约瑟夫环
{
LinkList p=L_list;
for(int i=0;i<n;i++)
{
for(int j=0;j<m-2;j++)
{
p=p->next;
}
LinkList q=p->next;
p->next=q->next;
printf("%d ",q->data);
free(q);
q=NULL;
p=p->next;
}
return 0;
}
主函数 main.c
#include "head.h"
int main(int argc, const char *argv[])
{
LinkList L_list=NULL; //定义结点变量,注意定义时一定要指向NULL
int n; //定义循环输入次数
ElemType value; //定义数据域元素
int seat; //定义元素位置
printf("please enter n:");
scanf("%d",&n);
for(int i=0;i<n;i++) //头插
{
printf("please enter a value:");
scanf("%d",&value);
L_list=insert_head(L_list,value);
}
for(int i=0;i<n;i++) //尾插
{
printf("please enter a value:");
scanf("%d",&value);
L_list=insert_rear(L_list,value);
}
L_list=delete_head(L_list); //头删
L_list=delete_rear(L_list); //尾删
Output(L_list);
//约瑟夫环
int m;
printf("please enter the number of people:");
scanf("%d",&n);
printf("please enter the number you want to break:");
scanf("%d",&m);
for(int i=0;i<n;i++)
{
L_list=insert_rear(L_list,i+1);
}
Joseph_loop(L_list,n,m);
return 0;
}