您的位置:首页 > 其它

约瑟夫问题-Josephus--及实例说明

2016-08-25 19:44 344 查看
类似约瑟夫的问题又称为约瑟夫环。又称“丢手绢问题”。

  这个问题来自于这样的一个关于著名犹太历史学家 Josephus传说: 在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

  约瑟夫问题是个有名的问题,比如6个人围一个圈,从第一个人开始123123的报数,最后一个报完了循环到第一个继续报数,报到数字3的人就退出游戏。这样退出的顺序就是: 3 6 4 2 5,最后剩下1一个人。


解决问题:

  就像题中描述的一样直接翻译成代码是(拯救约瑟夫的代码):

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
struct node {
int data;
struct node *prior, *next;
};
struct node *creat (int n, struct node *h) {
h = NULL;
struct node *s, *q;
for (int i = 1; i <= n; ++i) {
s =  (struct node *)malloc(sizeof (struct node));
s->data = i;
s->next = NULL;
if (h == NULL) {
h = s;
s->prior = h;
s->next = h;
} else {
s->next = q->next;
q->next = s;
s->prior = q;
h->prior = s;
}
q = s;
}
return h;
}
struct node *work (struct node *head, int m) {
struct node *p, *q;
p = head;
while (p->next != p) {
for (int i = 1;i < m; ++i) {
q = p;
p = p->next;
}
q->next = p->next;
p->next->prior = q;
printf ("%4d ", p->data);
free (p);
p = q->next;
}
return p;
}
int main () {
int m, n;    //n代表一共有n只猴子, m表示循环次数.
scanf ("%d%d", &n, &m);
struct node *head;
head = creat(n, head);
printf ("被删除的节点是:\n");
printf ("\n新大王是:%4d\n", work(head, m)->data);
return 0;
}


View Code
主要是练习双向链表的结构而已,原理和单向循环链表类似。

⑦、其实还有队列也可以实现,不过利用队列实现和方法③的思想就相似了,有想法的初学者小码友可以自己去操作一下。

  先总结这些,再有灵感再往上面加.欢迎批评。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: