zoukankan      html  css  js  c++  java
  • 约瑟夫环问题(Josephus Problem)C程序实现

    题目要求:编号为1,2,...n的n个人按顺时针的方向围坐一个圈,每个人持有一个密码.一开始任选一个正整数作为报数的上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数.报到m的人出列,将他的密码作为新的m的值,从他的顺时针方向的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止.  
      测试要求:m的初值为20,n=7,7个人的密码依次为:3   1   7   2   4   8   4.出列顺序应为6   1   4   7   2   3   5  

     

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

    struct node{
     int num;
     struct node *next;
    }a;

    struct node * creat(int n);               //返回头指针
    int excute(int m,struct node *head);//返回最后剩下的人的编号

    main()
    {
     int n;
     int m;
        struct node *h = NULL;

     printf("input how many people\n");
     scanf("%d",&n);
     printf("input which people been delete\n");
     scanf("%d",&m);
     if(n < 1 || m < 1){                   /*对特殊情况的讨论*/
      printf("wrong input!\n");
            return -1;
     }else if( n == 1 ){
      printf("nobady left!\n");
         return 0;
     }else if( m == 1 ){
            printf("the last number is %d\n",n);
      return 0;
     }else{
            h = creat(n);
         printf("\nthe last number is %d\n",excute(m,h));
         return 0;
     }
    }
     

    struct node * creat(int n)    //构造循环链表
    {
        struct node * p = NULL;
        struct node * h = NULL;
        struct node * q = NULL;
        int num = 0;

     p = (struct node *)malloc( sizeof(a) );
     p->num = ++num;
     p->next = NULL;
        h = p;
     while( --n !=0 ){
             q= (struct node *)malloc( sizeof(a) );
       q->num = ++num;
       p->next = q;
       p = q;
     }
     if(p != NULL)
      p->next = h;
     return h;
    }


    int excute(int m,struct node *h)
    {
     struct node *current=NULL;
        struct node * p=NULL;
     int i;

     current = h;
     printf("the out order is:");
     while (current->next != current){                                
               for (i = 1; i < m; i++){            /* 查找报数为m的小孩结点 */
       p = current;
                current = current->next;
       }
            p->next = current->next;               /* 删除报数为m的小孩结点 */
            printf("%5d",current->num);    //打印出被淘汰的顺序
            free(current);                        /* 释放报数为m的小孩结点空间 */
            current = p->next;
       }
     return current->num;
    }

    1,先确定数据结构为循环链表,每一个元素为一个结构,包括两个变量。再画一个图,找到解题的思路,写出大致的算法。

    2,根据画的图,先不考虑特殊的情况,写出代码。

    3,编译,链接,确保无错。

    4,加入安全方面的考虑,如非法输入等。

    5,加入易用性方面的代码。

    6,编译,链接,确保无错。

    之后可以参考一下别人的代码,可能会发现很多新的方法和思路。

    比如,这个题目也可以这样做:

     #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>                      //没有使用链表

    int main(int argc, char *argv[])
    {
        int m, n, step=0, index=0, cir=0;
        char *out=NULL;
        scanf("%d%d", &m, &n);
        out = (char*)malloc(m);//可以看作是数组的动态分配,好!!。与memset函数联合使用
        if(out == NULL) 
      return -1;
        memset(out, 0, m);   //因为malloc不对分配的内存进行初始化,所以这里用memset进行初始化
        while(1){
            if(step==m)
       break;
            while(cir<n) {
                if(!out[index])
        ++cir;
                index=(index+1)%m;         
            }    
            cir=0;
      ++step;
      out[(index+m-1)%m]=1;
            printf("\nNo.%d out.", !index?m:index);
        }   
        free(out);
        system("PAUSE");    //当有非法输入时,如0,5或4,0时,在屏幕上显示“请按任意键继续”
        return 0;
    }

    也可以这样做:

     /**********************************************
     *********     Josephus problem    ************
     *********************************************/    //和我的方法差不多
    #include <malloc.h>
    #include <stdio.h>
    struct boy /* struct of boy*/
    {
       int             num;
       struct boy     *next;
    };
    int main()
    {
       int             i;
       int             number;   /* 小孩的数目 */
       int             interval; /* 即报数从1- interval */
       struct boy     *head, *p, *current;

       printf("please input the number of boys:");
       scanf("%d", &number);
       printf("please input the interval:");
       scanf("%d", &interval);
       if(number < interval || number <= 0 || interval <= 0)
       {
         printf("input error!!!\n");
         return 0;
       }
       head = (struct boy *) malloc(sizeof(struct boy));
       head->num = 1;
       head->next = NULL;
       current = head;
       printf("Boy numbers:%d,", head->num);
       for (i = 2; i <= number; i++)/* 建立单向循环链表 */
       {
      p = (struct boy *) malloc(sizeof(struct boy));
      p->num = i;
      p->next = NULL;
      current->next = p;
      current = p;
      printf(" %d,", p->num);
       }
       printf("\n");
       current->next = head;
       current = head;
       printf("Out queue order:");
       while (current->next != current) /*loop to find the winner */
       {
      for (i = 1; i < interval; i++) /* 查找报数为interval的小孩结点 */
      {
     p = current;
     current = current->next;
      }
      p->next = current->next; /* 删除报数为interval的小孩结点 */
      printf(" %d,", current->num);
      free(current);    /* 释放报数为interval的小孩结点空间 */
      current = p->next;
       }
       printf("\n");
       printf("No.%d boy's won!\n", current->num);
       getch();
       return 0;
    }

     From:

    http://www.80diy.com/home/20050410/23/3924954.html

    http://dev.csdn.net/article/71/71711.shtm

    http://www.programfan.com/club/showpost.asp?id=21255&t=o

    http://tieba.baidu.com/f?kz=158638008

    http://baike.baidu.com/view/717633.htm

    http://blog.sina.com.cn/s/blog_4e5a13ad01009ccb.html

  • 相关阅读:
    树上差分
    Java学习笔记(二)事件监听器
    Java学习笔记(三)Java2D组件
    1066. Root of AVL Tree (25)
    有一种蓝,是神往,是心醉,是心伤
    软考论文的六大应对策略V1.0
    iOS 图形编程总结
    【悼鲁迅】诗一首
    【秋游】诗一首
    【游普罗旺斯薰衣草庄园】诗一首
  • 原文地址:https://www.cnblogs.com/emanlee/p/1292451.html
Copyright © 2011-2022 走看看