单循环链表解决约瑟夫环问题

关键字: 链表 约瑟夫环

     这几天为了准备笔试忙着复习C语言,决定把当时学C时的一些经典问题再温习一下,当时啊,学的稀里糊涂的,呵呵,现在回头来仔细写一写代码,就算是纪念当时的个性十足的赵老师了吧!
    约瑟夫问题的:编号为1,2,....,N的N个人按顺时针方向围坐一圈,每人持有一个密码(正整数),一开始任选一个正整数作为报数上限值M,从第一个人开始按顺时针方向自1开始顺序报数,报到M时停止报数。报M的人出列,将他的密码作为新的M值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。试设计一个程序求出出列顺序。
     解决思路还是很简单的,主要是要会熟练运用单循环链表的数据结构,通过单循环链表模拟围坐的一圈人,然后根据相应的密码进行报数,然后删除相应的链表节点。下面是C代码:

  1. #include <stdio.h>    
  2.  #include <stdlib.h>    
  3.  #define MAX_NODE_NUM 100    
  4.  #define TRUE 1U    
  5.  #define FALSE 0U    
  6.   
  7.  typedef struct NodeType    
  8.  {    
  9.       int id;    
  10.       int cipher;     
  11.            struct NodeType *next;    
  12.  } NodeType;    
  13.   
  14.  /* 创建单向循环链表 */    
  15.  static void CreaList(NodeType **, const int);    
  16.  /* 运行"约瑟夫环"问题 */    
  17.  static void StatGame(NodeType **, int);    
  18.  /* 打印循环链表 */    
  19.  static void PrntList(const NodeType *);    
  20.  /* 得到一个结点 */    
  21.  static NodeType *GetNode(const intconst int);    
  22.  /* 测试链表是否为空, 空为TRUE,非空为FALSE */    
  23.  static unsigned EmptyList(const NodeType *);    
  24.   
  25.  int main(void)    
  26.  {    
  27.        int n, m;    
  28.             NodeType *pHead = NULL;    
  29.             while (1)    
  30.             {    
  31.                 printf("请输入人数n(最多%d个): ", MAX_NODE_NUM);    
  32.                 scanf("%d", &n);    
  33.                 printf("和初始密码m: ");    
  34.                 scanf("%d", &m);    
  35.                 if (n > MAX_NODE_NUM)    
  36.                 {    
  37.                     printf("人数太多,请重新输入!\n");    
  38.                     continue;    
  39.                 }    
  40.                 else    
  41.                     break;    
  42.             }    
  43.             CreaList(&pHead, n);    
  44.             printf("\n------------ 循环链表原始打印 -------------\n");    
  45.             PrntList(pHead);    
  46.             printf("\n-------------删除出队情况打印 -------------\n");    
  47.             StatGame(&pHead, m);    
  48. }    
  49.   
  50.  static void CreaList(NodeType **ppHead, const int n)    
  51.  {    
  52.             int i, iCipher;    
  53.             NodeType *pNew, *pCur;    
  54.             for (i = 1; i <= n; i++)    
  55.             {    
  56.                 printf("输入第%d个人的密码: ", i);    
  57.                 scanf("%d", &iCipher);    
  58.                 pNew = GetNode(i, iCipher);    
  59.                 if (*ppHead == NULL)    
  60.                 {    
  61.                     *ppHead = pCur = pNew;    
  62.                     pCur->next = *ppHead;    
  63.                 }    
  64.                 else    
  65.                 {    
  66.                     pNew->next = pCur->next;    
  67.                     pCur->next = pNew;    
  68.                     pCur = pNew;    
  69.                 }    
  70.             }    
  71.             printf("完成单向循环链表的创建!\n");    
  72. }    
  73.   
  74. static void StatGame(NodeType **ppHead, int iCipher)    
  75. {    
  76.             int iCounter, iFlag = 1;    
  77.             NodeType *pPrv, *pCur, *pDel;    
  78.             pPrv = pCur = *ppHead;    
  79.             /* 将pPrv初始为指向尾结点,为删除作好准备 */    
  80.             while (pPrv->next != *ppHead)    
  81.                 pPrv = pPrv->next;    
  82.             while (iFlag)    
  83.             {     
  84.                 for (iCounter = 1; iCounter < iCipher; iCounter++)    
  85.                 {    
  86.                     pPrv = pCur;    
  87.                     pCur = pCur->next;    
  88.                 }    
  89.                 if (pPrv == pCur)    
  90.                     iFlag = 0;    
  91.                 pDel = pCur; /* 删除pCur指向的结点,即有人出列 */    
  92.                 pPrv->next = pCur->next;    
  93.                 pCur = pCur->next;    
  94.                 iCipher = pDel->cipher;    
  95.                 printf("第%d个人出列, 密码: %d\n", pDel->id, pDel->cipher);    
  96.                 free(pDel);    
  97.             }     
  98.             *ppHead = NULL;     
  99.             getchar();   
  100. }    
  101.   
  102. static void PrntList(const NodeType *pHead)    
  103. {    
  104.             const NodeType *pCur = pHead;    
  105.             if (EmptyList(pHead))    
  106.                 return;    
  107.             do    
  108.             {    
  109.                 printf("第%d个人, 密码: %d\n", pCur->id, pCur->cipher);    
  110.                 pCur = pCur->next;    
  111.             } while (pCur != pHead);    
  112.             getchar();   
  113. }    
  114.   
  115. static NodeType *GetNode(const int iId, const int iCipher)    
  116. {    
  117.             NodeType *pNew;    
  118.             pNew = (NodeType *)malloc(sizeof(NodeType));    
  119.             if(!pNew)    
  120.             {    
  121.                 printf("Error, the memory is not enough!\n");    
  122.                 exit(-1);    
  123.             }    
  124.             pNew->id = iId;    
  125.             pNew->cipher = iCipher;    
  126.             pNew->next = NULL;    
  127.             return pNew;    
  128. }    
  129.   
  130. static unsigned EmptyList(const NodeType *pHead)    
  131. {    
  132.             if(!pHead)    
  133.             {    
  134.                 printf("The list is empty!\n");    
  135.                 return TRUE;    
  136.             }    
  137.             return FALSE;    
  138. }  
原文地址:https://www.cnblogs.com/alamps/p/1690525.html