/************************************************************************/

/*                  Josephus问题——数组实现                          */

/************************************************************************/

#include

#include

int Josephus(int times, int number, int id){

int *a;

int i, count = 0, t = 0;

a = (int *)malloc(sizeof(int) * number);

for(i = 0; i < number; i++)

a[i] = i + 1;            // 数组a用于储存每个元素的编号

i = id - 1;

while(count < number - 1){

if(a[i] != 0)

t++;

if(t == times){

t = 0;

count++;

printf("%4d", a[i]);

a[i] = 0;                // 当该元素被剔除时,该数组元素置为0

}

i++;

if(i == number)

i = 0;

}

for(i=0;i

if(a[i]!=0)

{

printf("\n最后剩余的结点是:%4d\n",a[i]);

return;

}

}

int main(){

int times, number, id;

printf("请输入总人数:");

scanf("%d", &number);

printf("请输入报数周期:");

scanf("%d", &times);

printf("请输入开始报数的编号:");

scanf("%d", &id);

Josephus(times, number, id);

return 0;

}

/************************************************************************/

/* 总结:

优点为可以得出每次被剔除的元素编号

缺点为内存空间占用较大,没有数学归纳法快速                        */

/************************************************************************/

/************************************************************************/

/*                  Josephus问题——循环链表实现                      */

/************************************************************************/

#include

#include

typedef struct LNode

{

int data;

struct LNode *next;

}LNode,*Linkhead;

void Josephus(int m,int n,int k)

{

Linkhead p,r,head = NULL;

int i;

for(i = 1;i <= n;i++)

{

p = (Linkhead)malloc(sizeof(LNode));//申请一个新的链结点

p->data = i;//存放第i个结点的编号

if(head == NULL)

head = p;

else

r->next = p;      // 因为Insert和Del操作都需要之前一个节点的地址,故用r来存储。其作用类似栈的top

r = p;

}

p->next = head;//至此,建立一个循环链表

p = head;

for(i = 1;i < k;i++)

{

r=p;

/*请注意,此行不是多余的,因为当k!=1,但m=1时如果没有这条语句,此时删除动作无法完成*/

p=p->next;

}        //此时p指向第1个出发结点

while(p->next != p)

{

for(i = 1;i < m;i++)

{

r = p;

p = p->next;

}                        //p指向第m个结点,r指向第m-1个结点

r->next = p->next;        //删除第m个结点

printf("%4d",p->data);    //依次输出删除结点的编号

free(p);                //释放被删除结点的空间

p = r->next;            //p指向新的出发结点

}

printf("\n最后剩余的结点是:%4d\n",p->data);//输出最后一个结点的编号

}

int main(){

int times, number, id;

printf("请输入总人数:");

scanf("%d", &number);

printf("请输入报数周期:");

scanf("%d", &times);

printf("请输入开始报数的编号:");

scanf("%d", &id);

Josephus(times, number, id);

return 0;

}

/************************************************************************/

/* 总结:

优点为可以得出每次被剔除的元素编号

缺点为相较数组方法需要更多的计算量

总体而言与数组方法相差无几                                        */

/************************************************************************/

/************************************************************************/

/*            Josephus问题——数学归纳法直接计算                      */

/************************************************************************/

#include

int main() {

int answer = 0;

int times, number, i, id;    // number为环内总元素个数,times为报数周期, id为从第几个元素开始报数

printf("请分别输入总人数和循环次数:");

scanf("%d %d", &number, &times);

printf("起始报号者的编号:");

scanf("%d", &id);

for(i = 1; i <= number; i++) {

answer = (answer + times) % i;      // 核心算法,利用数学归纳法得出

}

if(answer + id == number)

printf("Survial: %d\n", number);    // 防止当幸存者为最后一个编号时输出0的情况

else

printf("Survival: %d\n",(answer + id) % number);

// 这边利用number对answer进行取余操作以防止编号数值超过最大编号(溢出)

return 0;

}

对于Josephus问题有两个地方是可以进行优化的。 (总人数为N,编号为从0~N-1;经过M次报数去除一个成员,剩余成员个数为numleft, 记M%numleft为mPrime)

1、被移除的成员离上一个成员之间的距离是M%numleft-1(报数次为M%numleft).当M大于N时,该计算方式将节省大量时间

2、当mPrime大于numleft的时候可以反向遍历该表来查找要去除的成员。这样可以节省时间。同样这也就要求了该表必须是一个双向表才行。(即含有Previous方法)

该算法实现原理即为:

第一轮,必定为编号M%N-1的成员被去除,第二轮为在第一轮的基础上即从编号为M%N的成员开始正移mPrime-1个单位(或者反移numleft-mPrime-1个单位)。若将M%N即为编号0,开始重新编号,那么第二轮被删除的成员编号便是M%(numleft)-1,由此可得该轮要被删除的成员与上一轮去除成员之间的距离为M%numleft,这里可利用迭代器来实现。

这里我们便可以得到成员编号与该轮成员数目的关系是:(n表示该轮所剩余的成员数目,Index(n)表示该轮成员的编号(从0开始))

Index(n) = (Index(n - 1) + m) % n。

那么按照这个过程,我们这样一直移除元素下去,肯定能够找到最后一个被移除的元素。

这个元素则对应只有一个元素的环,很显然,它的值为0。也就是Index(1) = 0。

对于这个元素的索引,它对应两个元素的索引是多少呢?

按照前面的过程,我们倒推回去就是了。Index(2) = (Index(1) + m) % 2。

那么对应3个,4个元素的呢?我们这样一路继续下去就可以找到对应到n个元素的索引了。

所以,我们发现了一个有意思的数学归纳关系:

f(1) = 0,  f(n) = (f(n - 1) + m) % n。

按照这个关系,我们可以得到最后一个被取出来的元素对应到n个元素的环里的索引值。

至此,我们可以发现,利用count计数从而删除成员的方法与此相比起来逊色不少,故之后我们将采用此方法来解决问题。

该问题的最终解决程序可参见另一篇文章: Java实现 Josephus约瑟夫环问题  http://www.linuxidc.com/Linux/2017-05/144055.htm

java约瑟夫环迭代器_Josephus约瑟夫环问题的不同实现方法与总结相关推荐

  1. java实现环形链表解决约瑟夫环问题

    什么是环形链表? 环形链表就是单向链表的基础上让链表的首尾相连,形成一个环,这就是一个循环链表. 什么是约瑟夫环问题? 约瑟夫环如下: 约瑟夫问题是个著名的问题:N个人围成一圈,第一个人从1开始报数, ...

  2. Java中使用链表解决约瑟夫问题(丢手绢问题)

    文章目录 文章目录 前言 一.思路分析 二.代码实现 1.Chird类建立 2.链表创建 3.功能实现 总结 其他解决方式: Java中使用list解决约瑟夫问题https://blog.csdn.n ...

  3. c语言链表如何做成环,在C语言中单向链表环测试并返回环起始节点的实现方法...

    小编想问大家一个问题,就是如果我们需要进行测试一个单向链表是否存在环,应该使用什么方法才是最好的呢?如果大家还不知道有什么方法的话,那就接着往下面看哟!因为今天小编就要为大家介绍一下:在C语言中单向链 ...

  4. 数据调度系统中有向无环图的无环检测

    数据调度系统中有向无环图的无环检测 名词解释 DAG,全称:Directed Acyclic Graph,中文:有向无环图 入度:有向图中某点作为图中边的终点的次数之和 出度: 对于有向图来说,顶点的 ...

  5. 【刷算法】判断链表是否有环以及返回入环节点

    题目描述 判断一个单链表是否有环,有环则返回入环节点,否则返回null 1->2->3->4->5->6↑ ↓8<-7 复制代码 例如上面这个链表就有环,入环节点是 ...

  6. STM32 电机教程 15 - BLDC 速度环内嵌电流环

    前言 无刷直流 (Brushless Direct Current, BLDC)电机是一种正快速普及的电机类型,它可在家用电器.汽车.航空航天.消费品.医疗.工业自动化设备和仪器等行业中使用.正如名称 ...

  7. 【学习笔记】无向图、有向图的三元环、四元环计数问题(根号分支+bitset)

    三元环计数和四元环计数问题 无向图三元环计数问题 根号分治 bitset 无向图四元环计数问题 有向图三四元环计数问题 无向图三元环计数问题 根号分治 记 di:id_i:idi​:i 在原图中的度数 ...

  8. Java中的迭代器设计模式–示例教程

    迭代器模式是一种行为模式,用于提供遍历一组对象的标准方式. Iterator模式在Java Collection Framework中得到了广泛使用,其中Iterator接口提供了遍历集合的方法. 根 ...

  9. ]数据结构:单链表之判断两个链表是否相交及求交点(带环、不带环)

    1.判断两个链表是否相交,若相交,求交点.(假设链表不带环) 两个指针同时指向两个链表,分别依次往后遍历链表到最后一个节点,如指针的值相同(即节点地址相同),反之没有交点. int IsCross(N ...

最新文章

  1. hadoop运行中报错笔记
  2. 【Java】Servlet 工作原理解析
  3. ceph单节点安装部署
  4. 《Android进阶之光》--View体系与自定义View
  5. 开源项目几点心得,Java架构必会几大技术点
  6. 2017.10.5 高速公路 思考记录
  7. C语言之预处理探究(三):头文件包含
  8. 在线node服务器,如何将你的node服务放到线上服务器
  9. 合成文字识别需要的训练竖排文字数据集
  10. 使用计算机辅助翻译的基本流程,计算机辅助翻译不同于机器翻译,计算机辅助翻译的原理和流程...
  11. java excel换行_java poi出excel换行问题
  12. 7. gdal进行遥感影像的16位转8位和百分比截断增强(看这篇就够了)
  13. 腾讯不缺少梦想,但是缺算法与数据管理
  14. 古今中外著名14大悖论
  15. 第三方支付(微信支付)支付流程分析
  16. HTML5 Canvas组件绘制太极图案
  17. Echarts实现省级到市级地图下钻
  18. Java中调整字距与行距的方法 其一(以DrawString为例)
  19. 如何实现web系统检测浏览器类型的功能
  20. 手机上传文件到ftp服务器,上传文件到iPhone上的FTP服务器(Upload File to FTP Server on i...

热门文章

  1. C++获取指向二维数组的首元素指针
  2. 从‘一边拉琴,一边哭’,看什么是真正的兴趣
  3. MFC中为菜单命令添加快捷键
  4. 三个数据集与deploy.prototxt
  5. CompletableFuture详解~thenApply
  6. java元素符号是什么_Java 代码中 @ 符号是什么意思?
  7. android点击通知后消失,通知栏点击后消失解决方法
  8. 外设驱动库开发笔记38:RTD热电阻测温驱动
  9. 记录---基于BigDecimal的特殊的四舍五入
  10. java post请求返回500错误信息_Retrofit API Post call 返回错误 500,适用于 Postman