约瑟夫问题(Josephus problem)的一点思考

原创 2007年10月01日 15:54:00
问题的提出:
假设N个人决定选出一个领导,将所有人排成一个圆周,沿着这个圆周每次数M个人就排除对应者,每当有人出列后,剩下的人靠拢,仍然保持一个完整的圆周。问题是找出最后剩下的那个人是谁(根据数学方法,不用这么麻烦,可能早就算出应该是圆周中的哪一个人了)。确定领导的过程是一个N和M的函数,这就是所谓的约瑟夫函数(Josephus  function)。更一般地讲,我们可能希望知道出列人员的顺序。例如,若共有N=9个人,且每数M=5个人就排除对应者,则出列顺序为5  1  7  4  3  6  9  2 ,8为选出的领导。

问题的解答:
问题的解决方式有多种,在此可以构造一个循环链表来解决问题。将N个人按顺序插入一个循环链表,然后从第一个人开始数M个人就删除一个节点,如此往复,直到剩下最后一个节点为止。为此,编写程序如下。
#include <stdlib.h>
#include <stdio.h>

typedef int Item;
typedef struct node *link;
struct node{
    Item item;
    link next;
};

int main(int argc,char *argv[])
{
    int i,N=atoi(argv[1]),M=atoi(argv[2]);
    link t=(link)malloc(sizeof(*t)),x=t;
    t->item=1;t->next=t;
    for(i=2;i<=N;i++){
        x=(x->next=(link)malloc(sizeof(*x)));
        x->item=i;
        x->next=t;
    }
    while(x!=x->next){
        for(i=1;i<M;i++)
            x=x->next;
        x->next=x->next->next;
        N--;
    }
    printf("%d/n",x->item);
    return 0;
}
以上程序的优点在于它能够快速删除节点,若使用数组而不是链表,则会使删除节点的开销增大。使用数组的优点在于它能快速访问数组中任意下标的元素。当我们选择一种数据结构时,必须当心这种选择对算法处理数据的效率的影响。
在C中,指针为链表的抽象概念提供了一种直接而且方便的具体实现,但抽象的基本值并不依赖于任何特定的实现。我们同样可以用整数数组来针对约瑟夫问题实现链表,也就是说,我们可以使用数组索引实现链表,而不是使用指针。下面的表就说明了链表的数组表示方法。具体实现程序有兴趣的话可以编写一下。
  0 1 2 3 4 5 6 7 8
item 1 2 3 4 5 6 7 8 9
next 1 2 3 4 5 6 7 8 0
链表的数组表示

在此,我给出我的实现如下:

#include <stdio.h>
#include <stdlib.h>

struct node{
 int item;
 int next;
};

void main(int argc,char *argv[2])
{
 int i,j,N=/*atoi(argv[1])*/9,M=/*atoi(argv[2])*/5;
 // 构造循环链表
 node *t=(node *)malloc(sizeof node *N);
 for(i=0;i<N;i++)
 {
  t[i].next=i+1;
  t[i].item=i+1;
 }
 t[N-1].next=0;
 i=0 ;
 // 模拟选举过程
 while(t[i].next!=i)  /* 该节点的next域不指向自己则继续循环*/
 {
  for(j=0;j<M-2;j++)
   i=t[i].next;
  t[i].next=t[t[i].next].next; /* 将i的next域值设置为其下下个节点的索引*/
  i=t[i].next;     /* 移到下一个节点*/
 }
 printf("%d",t[i].item);
}

当然,这个实现并不是唯一的,我们还可以分别用两个数组来表示,一个Item数组,一个next数组。大小均为N,然后并不修改Item,只修改next。

问题的反思:
算法的灵魂在于思想,不在实现,我们要掌握的是算法本身,而不是程序。程序只是我们算法的实现,不要拘泥于某一特定语言。语言只是工具而已,选用哪种语言,要看我们要解决的问题的规模,复杂度,时间以及空间的要求。当然,我并不是说不用学语言,而只去学数学。我们要学的是将算法的思想用具体的语言工具表达出来,解决实际遇到的问题。
最后,以上纯属本人愚见,不要当真,不同时期,总会有不同的体会,所以,尽情的享受学习带给你的快乐与困苦吧。

相关文章推荐

约瑟夫环问题(josephus problem)详解

约瑟夫环问题描述:   编号为1,2,3...n的人一词围成一圈,从第k个人开始报数(从1开始),数到m的人退出。接着下一个人又从1开始报数,数到m的人退出,以此类推。问:剩下的人的编号是多少?   ...

约瑟夫问题Josephus problem

约瑟夫问题:经典算法已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆...

约瑟夫环问题——Josephus Problem

Joseph ring - known to n - (numbered 1, 2, 3... n, respectively) sitting around a round table. Numbe...

约瑟夫问题(Josephus problem)

文章一:连接地址:http://blog.csdn.net/Melody_1208/archive/2007/10/01/1809005.aspx问题的提出:假设N个人决定选出一个领导,将所有人排成一...

josephus problem——约瑟夫问题

独立解josephus problem

约瑟夫问题(Josephus Problem)3:谁最后一个出列

版权所有。所有权利保留。 欢迎转载,转载时请注明出处: 本文是论述约瑟夫问题的第三部分,约瑟夫问题的描述在第一部分。请先阅读第一部分。 现在要求输出最后一个出列的人的编号。 第一次见到这个问题是在我高...

约瑟夫问题 The Josephus Problem 非递归算法求解

据说著名犹太历史学家 Josephus有过以下的故事: 在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,...
  • likerxu
  • likerxu
  • 2015年04月05日 21:24
  • 459

约瑟夫问题(Josephus problem)2:某人何时出列

版权所有。所有权利保留。 欢迎转载,转载时请注明出处: 本文是论述约瑟夫问题的第二部分,建立在第一部分基础上。请阅读第一部分后再阅读本文。 现在给定N和C,要求编号为id的那个人第几个出列。 这里采用...

约瑟夫问题(Josephus Problem)

算法历史描述: 说明据说着名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人到, ...

Josephus Problem 约瑟夫环问题的讨论

问题分析     Josephus环的问题看起来很简单,假设有n个人排成一个圈。从第一个人开始报数,数到第m个人的时候这个人从队列里出列。然后继续在环里数后面第m个人,让其出列直到所有人都出列。求所...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:约瑟夫问题(Josephus problem)的一点思考
举报原因:
原因补充:

(最多只允许输入30个字)