zoukankan      html  css  js  c++  java
  • 约瑟夫环(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("初始化链表错误!
    ");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("参与的人的编号为: ");

                              while (i<M)

                              {

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

                              p = p->next;

                              i++;

                      }

                      printf(" ");

    }

    (5)找到出局的人,并删除(删除算法)

      if(k > 1)//考虑出局密码为1时的情况

                  JoseDelete(h, N, k);

           else

           {

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

                         printf("出局的人为:%d号 ",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号 ",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("初始化链表错误!
    ");
     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("参与的人的编号为:
    ");
     52     while (i<M)
     53     {
     54         printf("%d	", p->Num);
     55         p = p->next;
     56         i++;
     57     }
     58     printf("
    ");
     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号
    ",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号
    ",i);
    117         printf("***************获胜者为:%d号***************",N);
    118     }
    119 
    120     printf("
    ");
    121     printf("
    ");
    122     return 0;
    123 }

    五、实验验证

      

      

    经过验证,实验成功!如果有不足的地方,请大家指出来,一起探讨!写得不清楚的可以与我联系。

    弱水三千,先干为敬。
  • 相关阅读:
    阿里云 ssl 证书 免费申请
    重启aliyun esc 需要重新启动redis
    SSL证书部署
    前端性能优化--合并请求
    npm 镜像修改
    google 浏览器插件安装
    离线安装.NET Framework 3.5
    A new session could not be created. (Original error: Could not find a connected Android device.)
    error: device unauthorized.
    pip 批量安装包
  • 原文地址:https://www.cnblogs.com/deom/p/4858010.html
Copyright © 2011-2022 走看看