首页 > 代码库 > 约瑟夫环问题

约瑟夫环问题

【问题描述】设编号为 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("\n%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("\n%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("\n%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---------------\n"); 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\n"); 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("\nKick Order: "); 99     KickFromRing(pHead, m);    100     printf("\n");101 }
View Code

 

约瑟夫环问题