约瑟夫环的三种解法

您所在的位置:网站首页 约瑟夫环简介 约瑟夫环的三种解法

约瑟夫环的三种解法

2024-05-06 02:58| 来源: 网络整理| 查看: 265

约瑟夫环(Josephus)问题是由古罗马的史学家约瑟夫(Josephus)提出的,他参加并记录了公元66—70年犹太人反抗罗马的起义。约瑟夫作为一个将军,设法守住了裘达伯特城达47天之久,在城市沦陷之后,他和40名死硬的将士在附近的一个洞穴中避难。在那里,这些叛乱者表决说“要投降毋宁死”。于是,约瑟夫建议每个人轮流杀死他旁边的人,而这个顺序是由抽签决定的。约瑟夫有预谋地抓到了最后一签,并且,作为洞穴中的两个幸存者之一,他说服了他原先的牺牲品一起投降了罗马。 约瑟夫环问题的具体描述是:设有编号为1,2,……,n的n(n>0)个人围成一个圈,从第1个人开始报数,报到m时停止报数,报m的人出圈,再从他的下一个人起重新报数,报到m时停止报数,报m的出圈,……,如此下去,直到所有人全部出圈为止。当任意给定n和m后,设计算法求n个人出圈的次序。

解法一:用循环链表实现代码语言:javascript复制#include #include typedef struct node { int data; struct node *next; }Node; /** * @功能 约瑟夫环 * @参数 total:总人数 * @参数 from:第一个报数的人 * @参数 count:出列者喊到的数 * @作者 zheng * @更新 2013-12-5 */ void JOSEPHUS(int total, int from, int count) { Node *p1, *head; head = NULL; int i; // 建立循环链表 for(i = 1; i data = i; if(NULL == head) { head = newNode; } else { p1->next = newNode; } p1 = newNode; } p1->next = head; // 尾节点连到头结点,使整个链表循环起来 p1 = head; // 使pcur指向头节点 // 把当前指针pcur移动到第一个报数的人 // 若从第一个人开始报数,这一段可要可不要 for(i = 1; i < from; i++) { p1 = p1->next; } Node *p2 = NULL; // 循环地删除队列中报到count的结点 while(p1->next != p1) { for(i = 1; i < count; i++) { p2 = p1; p1 = p1->next; } p2->next = p1->next; printf("Delete number: %d\n", p1->data); // 打印所要删除结点的数据 free(p1); // 删除结点,从内存释放该结点占用的内存空间 p1 = p2->next; // p1指针指向新的结点p2->next,即原先的p1->next } printf("The last one is No.%d\n", p1->data); } int main() { int total, from, count; scanf("%d%d%d", &total, &from, &count); JOSEPHUS(total, from, count); return 0; }

运行结果:

代码语言:javascript复制13 1 3 Delete number: 3 Delete number: 6 Delete number: 9 Delete number: 12 Delete number: 2 Delete number: 7 Delete number: 11 Delete number: 4 Delete number: 10 Delete number: 5 Delete number: 1 Delete number: 8 The last one is No.13解法二:数组实现

思路:设数组a有n个变量,每个变量中初始放的标识数是1,表示这个人在队列里,若出列标识数就变为0。 现在计数器从1开始向后数,每报一个数即把累加器加1。这里累加器表示报数人数。累列到m时,报数的人要出列,标识数要变为0。下一个人从1开始重新报数。 报到最后一个人后,从第一个人开始继续报数。

代码语言:javascript复制#include #include int main() { int n, m; scanf("%d%d", &n, &m); int flag[n + 1]; // 在队列里标记为1,出列标记为0 memset(flag, 0, sizeof(flag)); //把数组每个元素置0,在memory.h中声明 int i = 0; int outCnt = 0; // 记录出列的人数 int numoff = 0; // 报数 // 默认都标记为1 for(i = 1; i n >> m; cout > m; int out = 0; for(int i = 2; i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3