【问题描述】设编号为 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 }