链表有环的定义:链表的末尾指向了链表内的某个节点。
附:约瑟夫问题
#include "stdio.h"
#include "stdbool.h"
#include "stdlib.h"
#include "stdarg.h"
#include "string.h"
#include "math.h"
#include "time.h"
#include "errno.h"
typedef int Status;
typedef int Elemtype;
typedef struct node
{
Elemtype data;
struct node *next;
}Node;
typedef struct node* LinkCList;
void CycleListInit(LinkCList *CL);
void CycleListInsert(LinkCList *CL,int i);
void CycleListDelete(LinkCList *CL,int i);
void printfCList(LinkCList CL);
void Josephus(LinkCList *CL,int n);
// scanf(“%*[^\n]%*c”)} == fflush(stdin),刷新输入缓存区(去除非法字串)
// ^表示"非",[^\n]表示读入换行字符就结束读入。这个是scanf的正则用法,我们都知道scanf不能接收空格符,但是使用%[^\n]就可以了。
// *表示该输入项读入后不赋予任何变量,即scanf("%*[^\n]%*c")表示跳过一行字符串。
int main(void)
{
LinkCList L = NULL;
LinkCList L1 = NULL;
int i,num;
char ch;
printf("1.初始化结点\n2.插入结点\n3.删除结点\n4.打印该单循环链表\n5.约瑟夫问题\n(输入q退出)\n");
while(ch != '0')
{
scanf("%c",&ch);
switch(ch)
{
case '1':
CycleListInit(&L);
printfCList(L);
putchar('\n');
break;
case '2':
printf("输入要插入结点的位置:");
scanf("%d",&i);
CycleListInsert(&L,i);
printfCList(L);
putchar('\n');
break;
case '3':
printf("输入要删除结点的位置:");
scanf("%d",&i);
CycleListDelete(&L,i);
printfCList(L);
putchar('\n');
break;
case '4':
printfCList(L);
putchar('\n');
break;
case '5':
printf("本次约瑟夫环共有多少位元素?\n");
scanf("%d",&num);
Josephus(&L1,num);
break;
case 'q':
exit(0);
}
}
return 0;
}
void CycleListInit(LinkCList *CL)
{
LinkCList temp , rear;
Elemtype i;
printf("输入结点的值,输入0则完成初始化\n");
while(1)
{
scanf("%d",&i);
//fflush(stdin);
scanf("%*[^\n]%*c");
srand(time(0));
if(i == 0)
{
return;
}
if((*CL) == NULL)//空表
{
*CL = (LinkCList)malloc(sizeof(Node));
if(!(*CL))
{
printf("内存创建失败");
exit(1);
}
(*CL)->data = i;
(*CL)->next = *CL;
}
else
{
for(rear = (*CL); rear->next != (*CL);rear = rear->next);//找到末尾结点
temp = (LinkCList)malloc(sizeof(Node));
if(!temp)
{
printf("内存创建失败");
exit(1);
}
temp->data = i;
temp->next = *CL;//新结点指向头
rear->next = temp;//原来末尾的指向新结点
}
}
}
void CycleListInsert(LinkCList *CL,int i)
{
LinkCList temp,rear,newnode;
int j,newdata;
printf("输入插入结点的值:");
scanf("%d",&newdata);
if(i == 1)
{
newnode = (LinkCList)malloc(sizeof(Node));
if(!newnode)
{
printf("插入结点内存分配失败\n");
exit(1);
}
newnode->data = newdata;
for(rear = *CL;rear->next != *CL;rear = rear->next);
newnode->next = *CL;
rear->next = newnode;
*CL = newnode;
}
else
{
temp = *CL;
for(j = 1; j < i-1;j++)
{
temp = temp->next;
}
newnode = (LinkCList)malloc(sizeof(Node));
if(!newnode)
{
printf("插入结点内存分配失败\n");
exit(1);
}
newnode->data = newdata;
newnode->next = temp->next;
temp->next = newnode;
}
}
void CycleListDelete(LinkCList *CL,int i)
{
LinkCList temp,target;
int j = 1;
if(i == 1)
{
for(target = *CL;target->next != *CL;target = target->next);
temp = *CL;
*CL = (*CL)->next;
target->next = *CL;
free(temp);
}
else
{
target = *CL;
for(j = 1; j < i-1;j++)
{
target = target->next;
}
temp = target->next;
target->next = temp->next;
free(temp);
}
}
void printfCList(LinkCList CL)
{
LinkCList temp = CL;
if(!temp)
{
printf("该链表为空");
}
else
{
do
{
printf("%d ",temp->data);
}while((temp = temp->next) != CL);
}
putchar('\n');
}
void Josephus(LinkCList *CL,int n)
{
LinkCList temp,rear,now;
int i,m = 3;
if(n < 1)
{
return;
}
*CL = (LinkCList)malloc(sizeof(Node));
(*CL)->data = 1;
(*CL)->next = *CL;
for(rear = *CL;rear->next != *CL;rear = rear->next);
for(i = 1;i < n;i++)
{
temp = (LinkCList)malloc(sizeof(Node));
temp->data = i+1;
rear->next = temp;
temp->next = *CL;
rear = temp;
}
m %= n;//求余
now = *CL;
while(now != now->next)
{
for(i = 1;i < m-1 ;i++)//每次找到要删除的前一个结点
{
now = now->next;
}
printf("%d->",now->next->data);
now->next = now->next->next;
now = now->next;
}
printf("%d\n",now->data);
return;
}