一道模拟题:改进的Joseph环
题目:改进的Joseph环。一圈人报数,报数上限依次为3,7,11,19,循环进行,直到所有人出列完毕。
思路:双向循环链表模拟。
代码:
1 #include <cstdio> 2 #include <cstdlib> 3 4 #define N 20 5 6 typedef struct node 7 { 8 int id; 9 struct node *next; 10 struct node *pre; 11 }Node, *pNode; 12 13 //双向循环链表的构建 14 pNode RingConstruct (int n) 15 { 16 int i; 17 pNode head, p, q; 18 head = (pNode)malloc(sizeof(Node)); 19 head->id = 1; 20 p = head; 21 for (i = 2; i <= n; i++) 22 { 23 q = (pNode)malloc(sizeof(Node)); 24 q->id = i; 25 p->next = q; 26 q->pre = p; 27 p = q; 28 } 29 p->next = head; 30 head->pre = p; 31 return head; 32 } 33 34 //传入报数的次数序号,返回此次报数的上限值 35 int boundMachine (int order) 36 { 37 int boundList[4] = {3, 7, 11, 19}; 38 return boundList[(order - 1)%4]; 39 } 40 41 //first为每次报数的第一人,bound为此次报数的上限,返回此次报数的应出列者 42 pNode count (pNode first, int bound) 43 { 44 while (--bound) 45 { 46 first = first->next; 47 } 48 return first; 49 } 50 51 //将currentNode从环中删除,并返回被删除节点的下一节点 52 pNode removeNode (pNode currentNode) 53 { 54 pNode first = currentNode->next; 55 if (first != currentNode) 56 { 57 currentNode->pre->next = first; 58 first->pre = currentNode->pre; 59 } 60 printf("%d ", currentNode->id); 61 free(currentNode); 62 return first; 63 } 64 65 int main (int argc, char *argv) 66 { 67 pNode first, toRemove; 68 int i; 69 first = RingConstruct(N); 70 for (i = 1; i <= N; i++) 71 { 72 toRemove = count(first, boundMachine(i)); 73 first = removeNode(toRemove); 74 } 75 return 0; 76 }
当N为20时,出列顺序是: