题目:改进的Joseph环。一圈人报数,报数上限依次为3,7,11,19,循环进行,直到所有人出列完毕。
思路:双向循环链表模拟。
代码:
1 #include2 #include 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时,出列顺序是: