#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* 精简的瑟夫环问题
* N个人围着坐成一圈, 各自的编号从1到N, 可以从编号为1的人开始报数, 为接近现实情况,
* 报数从1开始, 设定一个报数的上限值M, 报数为M的人出列, 下一编号的人继续从1开始报
* 数, 问最后剩下人是那个编号?
* 例如: N=5, N=1时, 大家从1开始一次退出,最后剩下编号3; N=5, M=2时, 依次退出的
* 编号顺序为: 2, 4, 1, 5,最后剩下编号3; N=8, M=4时,
* 出列顺序为:4, 8, 5, 2, 1, 3, 7, 最后剩下6.
* 用户输入M, N值, 注意是从编号为1的人开始报数, 通用问题应该可以从编号为X的人开始。
*/
//使用链表
typedef struct _tRING_NODE_
{
int pos;
_tRING_NODE_ *next;
}tRING_NODE;
tRING_NODE* create_ring(int num)
{
if (num < 1) return NULL;
tRING_NODE *head = NULL;
tRING_NODE *ptr, *ptrTmp = NULL;
int i = 1;
while (num > 0)
{
ptr = new tRING_NODE;
ptr->pos = i++;
if (head == NULL)
head = ptrTmp = ptr;
ptrTmp->next = ptr;
ptrTmp = ptr;
--num;
}
ptrTmp->next = head; /* 循环链表 */
return head;
}
void show_ring(tRING_NODE *head)
{
if (head == NULL) return;
tRING_NODE *ptr = head;
while (1)
{
printf("%d->", ptr->pos);
if (ptr->next == head)
break;
ptr = ptr->next;
}
printf("\n");
}
void process_ring(tRING_NODE *head, int n, int m)
{
if (head == NULL || m < 1 || n < 1) return;
tRING_NODE *ptr = head, *ptrTmp = ptr;
int i = 1;
while (n != 1)
{
if (i == m) //删除ptr
{
if (ptr == head)
{
head = ptr->next;
ptrTmp->next = ptr->next;
//printf("out of queue No=%d\n", ptr->pos);
delete ptr;
if (ptrTmp == head)
ptrTmp = ptr = head;
else
ptr = ptrTmp->next;
i = 1;
--n;
continue;
}
ptrTmp->next = ptr->next;
//printf("out of queue No=%d\n", ptr->pos);
delete ptr;
ptr = ptrTmp->next;
i = 1;
--n;
}
else
{
ptrTmp = ptr;
ptr = ptr->next;
++i;
}
}
if (head != NULL)
{
head->next = head;
printf("1.with linklist, last No=%d\n", head->pos);
delete head; head = NULL;
}
}
//使用数组
void ysfh_question(int N, int M)
{
int *pArray = new int[N+1];
int n = N, step = 1, k = 1;
int flag = 1;
memset(pArray, 0x0, sizeof(int) * (N+1));
while (n != 1)
{
if (step == M)
{
//printf("delete ID=%d\n", k);
pArray[k] = 1;
while (pArray[k] != 0)
k = ((k+1 >= N+1)? (k+1)%N : k+1);
step = 1;
--n;
}
else
{
if (pArray[k] == 0)
{
if (flag != 0)
k = ((k+1 >= N+1)? (k+1)%N : k+1);
if (pArray[k] != 0)
{
k = ((k+1 >= N+1)? (k+1)%N : k+1);
flag = 0;
continue;
}
++step;
flag = 1;
}
else
{
flag = 0;
k = ((k+1 >= N+1)? (k+1)%N : k+1);
}
}
}
for (int i = 1; i <= N; ++i)
if (pArray[i] == 0)
printf("2.with array, Last No=%d\n", i);
delete []pArray; pArray = NULL;
}
int main(void)
{
int n, m;
printf("--- Josephus question ---\n");
printf("Input N(total number of the people):\n");
scanf("%d", &n);
printf("Input M(out number):\n");
scanf("%d", &m);
tRING_NODE *pHead = create_ring(n);
//show_ring(pHead);
process_ring(pHead, n, m);
ysfh_question(n, m);
return 0;
}