采用单向环表实现约瑟夫环。
请按以下要求编程实现:
- 从键盘输入整数m,通过create函数生成一个具有m个结点的单向环表。环表中的结点编号依次为1,2,……,m。
- 从键盘输入整数s(1<=s<=m)和n,从环表的第s个结点开始计数为1,当计数到第n个结点时,输出该第n结点对应的编号,将该结点从环表中消除,从输出结点的下一个结点开始重新计数到n,这样,不断进行计数,不断进行输出,直到输出了这个环表的全部结点为止。
例如,m=10,s=3,n=4。则输出序列为:6,10,4,9,5,2,1,3,8,7。
#include "stdio.h"
#include "stdlib.h"
struct Node // 结点定义
{
int order; // 序号
struct Node *next; // 下一个结点的指针
};
typedef struct Node Node;
Node *InitLIst() // 初始化环
{
Node *Head = (Node *)malloc(sizeof(Node));
Head->order = 1;
Head->next = Head;
return Head;
}
void Creat(Node *Head, int m) // 创建结点
{
int i;
Node *current = Head;
for (i = 2; i < m + 1; i++)
{
Node *p = (Node *)malloc(sizeof(Node));
p->order = i;
p->next = Head;
current->next = p;
current = p;
}
}
Node *Del(Node *Head, Node *current) // 删除结点
{
Node *p = Head;
if (Head->next == Head) // 如果只剩一个结点,直接删除
{
free(Head);
return NULL;
}
while (p->next != current) // 让p指向删除结点的前一个结点
{
p = p->next;
}
p->next = current->next;
if (Head == current) // 如果删除的是头结点,需要更新头结点
{
Head = p->next;
}
free(current);
return p->next;
}
int main()
{
int m, s, n, count;
int flag = 1;
Node *Head = InitLIst(); // 初始化环
Node *current = Head;
scanf("%d %d %d", &m, &s, &n); // 获取输入
Creat(Head, m); // 创建完整的环
for (int i = 1; i < s; i++) //使current到达第s个结点
{
current = current->next;
}
count = 1;
while (flag)
{
if (n != 1) //如果n不为1,则需要计数,n为1,直接逐个输出
{
current = current->next;
count++;
}
if (count == n)
{
printf("%d\n", current->order);
Node *nextNode = Del(Head, current);
if (current == Head) //如果当前结点是头结点,需要更新头结点
{
Head = nextNode;
}
current = nextNode;
if (current == NULL) //当前结点为空,停止循环
{
flag = 0;
break;
}
count = 1;
}
}
return 0;
}