约瑟夫环问题的解释及代码实现
2017-03-01 18:40
871 查看
约瑟夫环问题
故事背景:
据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39
个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
问题描述:
有n个人围成一个环,然后给从某个人开始顺时针从1开始报数,每报到m时,将此人出环杀死(当然不杀死也可以啊),然后从下一个人继续从1报数,直到最后只剩下一个人,求这个唯一剩下的存活的人是谁?
解决问题的核心步骤:(程序的基本算法)
1.建立一个具有n个链结点,无头结点的循环链表;
2.确定第1个报数人的位置;
3.不断地从链表中删除报数报到指定数num的那个人的链结点,直到链表剩一个节点。
pNode JosephCycle(pList* pplist, int num) //pplist是传进来的带环链表,num为出列者喊到的数
代码也很简单,直接看代码吧!
#include<stdlib.h>
#include<stdio.h>
#include<assert.h>
#include<windows.h>
#pragma warning(disable:4996)
typedef int DataType;
typedef struct Node
{
DataType data;
struct Node* next;
}Node, *pNode, *pList;
//初始化链表
void InitLinkList(pList* pplist)
{
assert(pplist != NULL);
*pplist = NULL;
}
//创建一个节点空间
pNode BuyNode(DataType d)
{
pNode temp = NULL;
temp = (pNode)malloc(sizeof(Node));
temp->data = d;
temp->next = NULL;
return temp;
}
//在链表上尾插节点
void PushBack(pList* pplist, DataType d)
{
assert(pplist != NULL);
pNode NewNode = BuyNode(d);
pNode cur = *pplist;
if (*pplist == NULL)
{
*pplist = NewNode;
return;
}
while (cur->next != NULL)
{
cur = cur->next;
}
cur->next = NewNode;
return;
}
//寻找并返回指定结点的地址
pNode Find(pList plist, DataType d)
{
pNode cur = plist;
if (cur == NULL)
{
printf("链表为空,");
return NULL;
}
while (cur != NULL)
{
if (cur->data == d)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
//约瑟夫环问题代码
pNode JosephCycle(pList* pplist, int num)
{
int i = 0;
pNode del = NULL;
pNode cur = *pplist;
assert(pplist);
while (1)
{
if (cur->next == cur) //判断链表上是否只有一个节点,如果是则返回这个节点
{
return cur;
}
for (i = 0; i < num - 1; i++) //找出报数报到num的人,每报到num的人就跳出链表,然后删除
{
cur = cur->next;
}
del = cur->next;
printf("%d\n", cur->data);
cur->data = cur->next->data;
cur->next = cur->next->next;
free(del);
}
}
int main()
{
pList plist;
pNode ret = NULL;
InitLinkList(&plist); //初始化链表
PushBack(&plist, 1); //这里可以随意设置链表的长度
PushBack(&plist, 3);
PushBack(&plist, 5);
PushBack(&plist, 7);
PushBack(&plist, 8);
Find(plist, 8)->next = plist; //构造环
printf("依次报到指定数字的人:\n");
ret = JosephCycle(&plist, 3); //这里设置报数每报到三的出列
printf("最后一个人是:\n%d\n", ret->data);
return 0;
}
故事背景:
据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39
个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
问题描述:
有n个人围成一个环,然后给从某个人开始顺时针从1开始报数,每报到m时,将此人出环杀死(当然不杀死也可以啊),然后从下一个人继续从1报数,直到最后只剩下一个人,求这个唯一剩下的存活的人是谁?
解决问题的核心步骤:(程序的基本算法)
1.建立一个具有n个链结点,无头结点的循环链表;
2.确定第1个报数人的位置;
3.不断地从链表中删除报数报到指定数num的那个人的链结点,直到链表剩一个节点。
pNode JosephCycle(pList* pplist, int num) //pplist是传进来的带环链表,num为出列者喊到的数
代码也很简单,直接看代码吧!
#include<stdlib.h>
#include<stdio.h>
#include<assert.h>
#include<windows.h>
#pragma warning(disable:4996)
typedef int DataType;
typedef struct Node
{
DataType data;
struct Node* next;
}Node, *pNode, *pList;
//初始化链表
void InitLinkList(pList* pplist)
{
assert(pplist != NULL);
*pplist = NULL;
}
//创建一个节点空间
pNode BuyNode(DataType d)
{
pNode temp = NULL;
temp = (pNode)malloc(sizeof(Node));
temp->data = d;
temp->next = NULL;
return temp;
}
//在链表上尾插节点
void PushBack(pList* pplist, DataType d)
{
assert(pplist != NULL);
pNode NewNode = BuyNode(d);
pNode cur = *pplist;
if (*pplist == NULL)
{
*pplist = NewNode;
return;
}
while (cur->next != NULL)
{
cur = cur->next;
}
cur->next = NewNode;
return;
}
//寻找并返回指定结点的地址
pNode Find(pList plist, DataType d)
{
pNode cur = plist;
if (cur == NULL)
{
printf("链表为空,");
return NULL;
}
while (cur != NULL)
{
if (cur->data == d)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
//约瑟夫环问题代码
pNode JosephCycle(pList* pplist, int num)
{
int i = 0;
pNode del = NULL;
pNode cur = *pplist;
assert(pplist);
while (1)
{
if (cur->next == cur) //判断链表上是否只有一个节点,如果是则返回这个节点
{
return cur;
}
for (i = 0; i < num - 1; i++) //找出报数报到num的人,每报到num的人就跳出链表,然后删除
{
cur = cur->next;
}
del = cur->next;
printf("%d\n", cur->data);
cur->data = cur->next->data;
cur->next = cur->next->next;
free(del);
}
}
int main()
{
pList plist;
pNode ret = NULL;
InitLinkList(&plist); //初始化链表
PushBack(&plist, 1); //这里可以随意设置链表的长度
PushBack(&plist, 3);
PushBack(&plist, 5);
PushBack(&plist, 7);
PushBack(&plist, 8);
Find(plist, 8)->next = plist; //构造环
printf("依次报到指定数字的人:\n");
ret = JosephCycle(&plist, 3); //这里设置报数每报到三的出列
printf("最后一个人是:\n%d\n", ret->data);
return 0;
}
相关文章推荐
- 约瑟夫问题的单向循环链表的代码实现
- 10行python代码实现约瑟夫问题
- 01背包问题算法解释与C代码实现
- Dijstra算法的代码实现及解释(最短路径问题)
- 约瑟夫问题解决及实现代码(C语言版)
- 自己用java代码实现的:“约瑟夫”问题
- 约瑟夫问题及其实现代码
- 约瑟夫问题总结及代码实现
- 约瑟夫问题总结及代码实现
- “约瑟夫问题”实现代码
- 约瑟夫问题分析及代码实现
- “约瑟夫问题”实现代码加运行截图(ADT小组)
- “约瑟夫问题”实现代码
- 约瑟夫问题java语言实现代码
- 约瑟夫问题的数组实现
- 约瑟夫(Josephus)问题的实现
- 折半查找实现算法二(递归办法)PS:编译后有一个warning,但不影响结果,代码设计上应该还有些问题
- 人狼羊菜过河问题 (Java代码实现)
- MinimizeName在C#中的实现代码(解决了我那个GDI+的问题)
- access如何用代码在“默认值”里实现自动编号?单据流水号生成问题。