約瑟夫環(N個人圍桌,C語言,數據結構)


約瑟夫環問題(C語言、數據結構版)

一、問題描述

N個人圍城一桌(首位相連),約定從1報數,報到數為k的人出局,然后下一位又從1開始報,以此類推。最后留下的人獲勝。(有很多類似問題,如猴子選代王等等,解法都一樣)

二、思路分析

  (1)可將人的順序簡單編號,從1到N;

  (2)構造一個循環鏈表,可以解決首位相連的問題,同時如果將人的編號改為人名或者其他比較方便

  (3)將人的編號插入到結構體的Data域;

  (4)遍歷人的編號,輸出參與的人的編號;

  (5)開始報數,從頭報數,報到k的人出局(刪除次結點),(輸出出局的人更人性化)避免浪費,可釋放次結點。直到人數只有一個人時,退出循環。輸出獲勝的人。

  (6)注意:在寫刪除刪除結點的函數時都是針對K>=2的情況處理,所以要考慮k=1的情況,要是出局的密碼為1時則最后一個獲勝。

三、算法實現

      (1)構造結構體

typedef struct Node{
        int Num;//Data域
        struct Node *next;
    }JoseNode, *PNode, *HNode;//PNode為指針變量,HNode為頭結點        

       (2)得到頭結點

HNode h = ((HNode)malloc(sizeof(JoseNode)));

  (3)初始化循環單鏈表

 int JoseInit(HNode *h)
    {
        if (!h)
        {
         printf("初始化鏈表錯誤!\n");return 0;

        }
        (*h)->next = (*h);//循環單鏈表
        return 1;
    }                        

(4)插入算法

          

 int JoseInsert(JoseNode *h, int pos, int x)
{      
        PNode p=h,q;
        int i=1;if (pos == 1)/*尾插法*/
        {
               p->Num = x;
               p->next = p;
               return 1;
         }
        while(i<pos-1)
        {
        p=p->next;
        i++;
        }
        q=(PNode)malloc(sizeof(JoseNode));
        q->Num=x;
        q->next=p->next;
        p->next=q;
        return 1;
}        
for (i = 1; i <=N; i++)
    {
        JoseInsert(h, i, i);
    }

 

(4)遍歷算法

void TraverseList(HNode h, int M)

{

                          int i = 0;

                          PNode p = h;

                           printf("參與的人的編號為:\n");

                          while (i<M)

                          {

                          printf("%d\t", p->Num);

                          p = p->next;

                          i++;

                  }

                  printf("\n");

}

 

(5)找到出局的人,並刪除(刪除算法)

  if(k > 1)//考慮出局密碼為1時的情況

              JoseDelete(h, N, k);

       else

       {

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

                     printf("出局的人為:%d號\n",i);

              printf("***************獲勝者為:%d號***************",N);

       }

 

 

      int JoseDelete(HNode h, int M, int k)

{       int i;

                  PNode p=h,q;

                  while(M>1)//循環終止條件,只剩一個人時

                  {

                          for(i=1;i<k-1;i++)//此處為i<k-1,因為要找到的是出局的人的前一個結點①

                          {

                                   p=p->next;

                          }

                 

                          q=p->next;

                          p->next=q->next;

                           printf("出局的人為:%d號\n",q->Num);

                          free(q);//釋放次結點

 

                          p=p->next;//與①處的相對應,①處找到的只是出局的人的前一個結點

                          M--;

                  }

         printf("***************獲勝者為:%d號***************",p->Num);

         return 1;

}

 

 

四、完整代碼

  

  1 #include <stdio.h>
  2 #include <malloc.h>
  3 
  4 /*構建結構體*/
  5 typedef struct Node{
  6     int Num;
  7     struct Node *next;
  8 }JoseNode, *PNode, *HNode;
  9 
 10 /**********初始化循環單鏈表*********/
 11 int JoseInit(HNode *h)
 12 {
 13     if (!h)
 14     {
 15         printf("初始化鏈表錯誤!\n");
 16         return 0;
 17     }
 18     (*h)->next = (*h);//循環單鏈表
 19     return 1;
 20 
 21 }
 22 
 23 /*************單鏈表插入操作**********/
 24 int JoseInsert(JoseNode *h, int pos, int x)
 25 {    
 26     PNode p=h,q;
 27     int i=1;
 28     if (pos == 1)/*尾插法*/
 29     {
 30         p->Num = x;
 31         p->next = p;
 32         return 1;
 33     }
 34     while(i<pos-1)
 35     {
 36         p=p->next;
 37         i++;
 38     }
 39     q=(PNode)malloc(sizeof(JoseNode));
 40     q->Num=x;
 41     q->next=p->next;
 42     p->next=q;
 43     return 1;
 44 }
 45 
 46 /*遍歷*/
 47 void TraverseList(HNode h, int M)
 48 {
 49     int i = 0;
 50     PNode p = h;
 51     printf("參與的人的編號為:\n");
 52     while (i<M)
 53     {
 54         printf("%d\t", p->Num);
 55         p = p->next;
 56         i++;
 57     }
 58     printf("\n");
 59 }
 60 /**************出局函數****************/
 61 
 62 int JoseDelete(HNode h, int M, int k)
 63 {    int i;
 64     PNode p=h,q;
 65     while(M>1)
 66     {
 67         for(i=1;i<k-1;i++)
 68         {
 69             p=p->next;
 70         }
 71         
 72         q=p->next;
 73         p->next=q->next;
 74         printf("出局的人為:%d號\n",q->Num);
 75         free(q);
 76 
 77         p=p->next;
 78         M--;
 79     }
 80     printf("***************獲勝者為:%d號***************",p->Num);
 81     return 1;
 82 }
 83 
 84 
 85 /***************************************/
 86 int main()
 87 {
 88     int i;//計數器
 89     int N;//參與的人數
 90     int k;//報數密碼
 91     printf("請輸入參與人數:");
 92     scanf("%d",&N);
 93     printf("請輸入出局密碼:");
 94     scanf("%d",&k);
 95 
 96 /**************得到頭結點****************/
 97     HNode h = ((HNode)malloc(sizeof(JoseNode)));
 98 
 99 /***************初始化單鏈表************/
100     JoseInit(&h);
101 
102 /******將編號插入到循環單鏈表中******/
103     for (i = 1; i <=N; i++)
104     {
105         JoseInsert(h, i, i);
106     }
107 /**************遍歷單鏈表***************/
108     TraverseList(h,N);
109 
110 /***************出局函數************/
111     if(k > 1)
112     JoseDelete(h, N, k);
113     else
114     {
115         for(i = 1; i < N; i++)
116             printf("出局的人為:%d號\n",i);
117         printf("***************獲勝者為:%d號***************",N);
118     }
119 
120     printf("\n");
121     printf("\n");
122     return 0;
123 }

 


五、實驗驗證

  

  

 

經過驗證,實驗成功!如果有不足的地方,請大家指出來,一起探討!寫得不清楚的可以與我聯系。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM