約瑟夫環問題(Josephus Problem)C程式實現

來源:互聯網
上載者:User

題目要求:編號為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

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.