一、单向循环链表的描述
循环链表:是另一种形式的链式存储结构。其特点是表中最后一个结点的指针域指向头节点,整个链表形成一个环。
单向循环链表的操作和单链表操作基本一致,差别在于:当链表遍历时,判别当前指针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; //定义结点变量,注意定义时一定要指向NULLint 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;
}