2007-08-22

    约瑟夫环问题(Josephus) - [Algorithms]

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://conoon.blogbus.com/logs/7856112.html

    原题:
        用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。写出C程序。(约瑟夫环问题 Josephus)

    提示:
        由于当某个人退出圆圈后,报数的工作要从下一个人开始继续,剩下的人仍然是围成一个圆圈的,可以使用循环表,由于退出圆圈的工作对应着表中结点的删除操作,对于这种删除操作频繁的情况,选用效率较高的链表结构,为了程序指针每一次都指向一个具体的代表一个人的结点而不需要判断,链表不带头结点。所以,对于所有人围成的圆圈所对应的数据结构采用一个不带头结点的循环链表来描述。设头指针为p,并根据具体情况移动。
        为了记录退出的人的先后顺序,采用一个顺序表进行存储。程序结束后再输出依次退出的人的编号顺序。由于只记录各个结点的number值就可以,所以定义一个整型一维数组。如:int  quit[n];n为一个根据实际问题定义的一个足够大的整数。

    代码:

    /********************************************************************
     purpose: 实现 Josephus 环问题,用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。写出C程序。(约瑟夫环问题 Josephus)
    *********************************************************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <malloc.h>

    /* 结构体和函数声明 */
    typedef struct _node_t
    {
     int n_num;
     struct _node_t *next;
    } node_t;

    node_t *node_t_create(int n);
    node_t *node_t_get(node_t **pn, int m);

    /* 功能函数实现 */
    /*
     * name: node_t_create
     * params:
     * n [in]    输入要构造的链表的个数
     * return:   返回构造成功的环形单向链表指针
     * notes :    构造节点数量为 n 的环形单向链表
     *
     *
     */
    node_t *node_t_create(int n)
    {
     node_t *p_ret = NULL;
     if (0 != n)
     {
      int n_idx = 1;
      node_t *p_node = NULL;
      p_node = (node_t *)malloc(n*sizeof(node_t)); /* 构造 n 个 node_t */
      if (NULL == p_node)
       return NULL;
      else
       memset(p_node, 0, n*sizeof(node_t)); 
      p_ret = p_node;/* 内存空间申请成功 */
      for (; n_idx < n; n_idx++)
      {
       p_node->n_num = n_idx;
       p_node->next = p_node+1;
       p_node = p_node->next;
      }
      p_node->n_num = n;
      p_node->next = p_ret;
     }
     return p_ret;
    }

    int main()
    {
     int n, m;
     node_t *p_list, *p_iter;
     n = 20; m = 6;
     p_list = node_t_create(n);/* 构造环形单向链表 */
     p_iter = p_list;/* Josephus 循环取数 */
     m %= n;
     while (p_iter != p_iter->next)
     {
      int i = 1;
      for (; i < m-1; i++) /* 取到第 m-1 个节点 */
      {
       p_iter = p_iter->next;
      } 
      printf("%d\n", p_iter->next->n_num);  /* 输出第 m 个节点的值 */
      p_iter->next = p_iter->next->next;    /* 从链表中删除第 m 个节点 */
      p_iter = p_iter->next;
     }
     printf("%d\n", p_iter->n_num);
     free(p_list); /* 释放申请的空间 */
     system("PAUSE");
    }


    收藏到:Del.icio.us




    Tag:
    引用地址:

发表评论

您将收到博主的回复邮件
记住我