#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;
}