约瑟夫(Josephus)环问题:
编号为1,2,3,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数的上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一人开始重新从1报数,如此下去,直到所有人全部出列为止。建立n个人的单循环链表存储结构,运行结束后,输出依次出队的人的序号。
思路
将n个人的password依次输入,将每个人的id,password,next写入一个结构体,形成链表的一个节点,写入并创建为单循环链表。
然后再进行循环删除列表元素,记得free防止memory leak
另外注意当m == 1并且当前节点为head时情况处理有所不同需要拿出讨论。
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<mm_malloc.h>
using namespace std;
typedef struct LNode
{
int id;
int password;
struct LNode *next;
}LNode,*LinkList; //节点指针变量和头指针
int a[10000] = {
0};
LNode *pHead;
void CreateList(int n);
void Josephus(int m, int n);
int main()
{
int m,n;
cin>>m>>n;
for(int i = 0;i < n;i++)
{
cin>>a[i];
}
CreateList(n);
Josephus(m,n);
return 0;
}
void CreateList(int n)
{
LNode *pNew;
LNode *pEnd = (LNode*)malloc(sizeof(LNode));
for(int i = 0;i < n;i++)
{
pNew = (LNode*)malloc(sizeof(LNode));
pNew->id = i + 1;
pNew->password = a[i];
if(i == 0)
{
pHead = pNew;
}
else
{
pEnd->next = pNew; //表示上一个节点的下一个节点是本节点
}
pNew->next = pHead; //循环
pEnd = pNew; //end赋为新地址
}
}
void Josephus(int m,int n)
{
LNode *p = pHead;
LNode *target = pHead;
int number = 0;
while(n--)
{
if(m == 1 && p == pHead)//1是特殊情况
{
while(p->next != pHead) // 找到tail
{
p = p->next;
}
target = pHead;
m = target->password;
number = target->id;
p->next = pHead->next;
free(pHead);
pHead = p->next;
p = pHead;
}
else
{
LNode * q;
int i = 1;
while(m != i)
{
q = p;
p = p->next;
i++;
}
target = p;
q->next = p->next;
m = target->password;
number = target->id;
free(p);
p = target->next; //target的下一个元素继续开始
}
cout<<number<<endl;
}
}