思考这样一个问题:你和另外40个人被一个野蛮的部落包围了,酋长要求你们围成一个圆圈,从第1个位置上的人开始报数,报到3的人将会被杀掉。这个过程沿着圆圈一直继续,直到剩下最后一个人,这个人可以安全地离开。你要选择站在第几个位置才能成为那个幸运的幸存者呢?
这就是有名的约瑟夫环问题。下面我们就来探讨一下几种解决方案。
链表法
不难看出,这个问题非常适合使用循环链表求解。建立一个包含41个元素的循环链表,从表头开始进行循环遍历,模拟圆圈报数的过程,遇到报到3的元素就把这个元素删掉,直到链表中仅剩下最后一个元素。
C语言实现:
#include <stdio.h>
#include <stdlib.h>
#define TOTAL 41
#define COUNT 3
struct llist_t {
int index;
struct llist_t *pNext;
};
int main() {
int i;
struct llist_t *pHead = malloc(sizeof(struct llist_t) * TOTAL);
struct llist_t *pCurrent = pHead;
if (pHead == NULL) {
printf("Malloc failed.\n");
return 1;
}
// Initialize the array.
for (i = 0; i < TOTAL; ++i) {
pHead[i].index = i + 1;
pHead[i].pNext = pHead + ((i + 1) % TOTAL);
}
// Run the process.
while (pCurrent->pNext != pCurrent) {
for (i = 0; i < COUNT - 1; ++i) {
if (i == COUNT - 2)
pCurrent->pNext = pCurrent->pNext->pNext;
pCurrent = pCurrent->pNext;
}
}
printf("The survivor is the person in position %d.\n", pCurrent->index);
free(pHead);
return 0;
}