约瑟夫环问题

【问题描述】设编号为 1 , 2 , ……, n 的 n ( n >0 ) 个人围成一个圈,每人持有一个密码 m ,从 数,报到 m 时停止报数,报 m 的出圈,……,如此下去,直到所有人全部出圈为止。当 任意给定 n 和 m 后,设计算法求 n 个人出圈的次序。 
 
【数据结构分析】
由于约瑟夫环本身问题具有循环性质,考虑用循环链表解决该问题。

【问题分析】
建立单链表后,通过初始密码找到出列的结点,输出该结点的序号, 将该结点中的密码值作为下一轮的初始密码,将该结点从链表中删除, 并释放该结点的空间。重复此过程,直到剩下最后一个结点,就直接将该结点中的序号删除, 删除该结点,并释放该结点的空间。 
 
【程序代码(C语言)】
  1 /*
  2  约瑟夫环问题(Josephus)
  3 */
  4 #include <stdio.h>
  5 #include <stdlib.h>
  6 
  7 // 链表节点
  8 typedef struct _RingNode
  9 {
 10     int pos;  // 位置
 11     struct _RingNode *next;
 12 }RingNode, *RingNodePtr;
 13 
 14 // 创建约瑟夫环,pHead:链表头指针,count:链表元素个数
 15 void CreateRing(RingNodePtr pHead, int count)
 16 {
 17     RingNodePtr pCurr = NULL, pPrev = NULL;
 18     int i = 1;
 19     pPrev = pHead;
 20     while(--count > 0)
 21     {
 22         pCurr = (RingNodePtr)malloc(sizeof(RingNode));
 23         i++;
 24         pCurr->pos = i;
 25         pPrev->next = pCurr;
 26         pPrev = pCurr;
 27     }
 28     pCurr->next = pHead;  // 构成环状链表
 29 }
 30 
 31 void PrintRing(RingNodePtr pHead)
 32 {
 33     RingNodePtr pCurr;
 34     printf("%d", pHead->pos);
 35     pCurr = pHead->next;
 36     while(pCurr != NULL)
 37     {
 38         if(pCurr->pos == 1)
 39             break;
 40         printf("
%d", pCurr->pos);
 41         pCurr = pCurr->next;
 42     }
 43 }
 44 
 45 void KickFromRing(RingNodePtr pHead, int m)
 46 {
 47     RingNodePtr pCurr, pPrev;
 48     int i = 1;    // 计数
 49     pCurr = pPrev = pHead;
 50     while(pCurr != NULL)
 51     {
 52         if (i == m)
 53         {
 54             // 踢出环
 55             printf("
%d", pCurr->pos);    // 显示出圈循序
 56             pPrev->next = pCurr->next;
 57             free(pCurr);
 58             pCurr = pPrev->next;
 59             i = 1;
 60         }
 61         pPrev = pCurr;
 62         pCurr = pCurr->next;
 63         if (pPrev == pCurr)
 64         {
 65             // 最后一个
 66             printf("
%d", pCurr->pos);    // 显示出圈循序
 67             free(pCurr);
 68             break;
 69         }
 70         i++;
 71     }
 72 }
 73 
 74 int main()
 75 {
 76     int m = 0, n = 0;
 77     RingNodePtr pHead = NULL;
 78     printf("---------------Josephus Ring---------------
");
 79     printf("N(person count) = ");
 80     scanf("%d", &n);
 81     printf("M(out number) = ");
 82     scanf("%d", &m);
 83     if(n <= 0 || m <= 0)
 84     {
 85         printf("Input Error
");
 86         system("pause");
 87         return 0;
 88     }
 89     // 建立链表
 90     pHead = (RingNodePtr)malloc(sizeof(RingNode));
 91     pHead->pos = 1;
 92     pHead->next = NULL;
 93     CreateRing(pHead, n);
 94     #ifdef _DEBUG
 95     PrintRing(pHead);
 96     #endif
 97     // 开始出圈
 98     printf("
Kick Order: ");
 99     KickFromRing(pHead, m);    
100     printf("
");
101 }
View Code
原文地址:https://www.cnblogs.com/dingyichao/p/4021418.html