展开查看
约瑟夫问题是一个经典的问题(大一我们讲过)。这个问题可以用数组,也可以用链表。作为复习,大家可以试试你自己的算法。
已知n个人(不妨分别以编号1,2,3,…,n 代表 )围坐在一张圆桌周围,从编号为 k 的人开始,从1开始顺时针报数1, 2, 3, ...,顺时针数到m 的那个人,出列并输出。然后从出列的下一个人开始,从1开始继续顺时针报数,数到m的那个人,出列并输出,…依此重复下去,直到圆桌周围的人全部出列。
输入:n, k, m
输出:按照出列的顺序依次输出出列人的编号,编号中间相隔一个空格,每10个编号为一行。
非法输入的对应输出如下
a)
输入::n、k、m任一个小于1
输出:n,m,k must bigger than 0.
b)
输入:k>n
输出:k should not bigger than n.
例:
输入:9,3,2
输出:4 6 8 1 3 7 2 9 5
#include<stdio.h> #include<stdlib.h> typedefstructNode { int data; structNode* next; } NODE; NODE* createNode(int data) { NODE* newNode = (NODE*)malloc(sizeof(NODE)); newNode->data = data; newNode->next = newNode; // 初始化为指向自身 return newNode; } // 插入节点到循环链表的末尾 voidinsertNode(NODE** head, int data) { NODE* newNode = createNode(data); if (*head == NULL) { *head = newNode; // 如果链表为空,新的节点成为头节点 } else { NODE* temp = *head; while (temp->next != *head) { temp = temp->next; // 找到最后一个节点 } temp->next = newNode; // 将最后一个节点的next指向新节点 } newNode->next = *head; // 新节点指向头节点,形成循环 } voidfreeList(NODE* head) { if (head == NULL) return; NODE* current = head; NODE* nextNode; do { nextNode = current->next; free(current); current = nextNode; } while (current != head); } voidbaka(int k, NODE** head) { NODE* temp = *head; for (int i = 1; i < k; i++) { temp = temp->next; } *head = temp; } intcirno(int m, NODE** head) { int data; NODE* temp = *head; for (int i = 1; i < m - 1; i++) temp = temp->next; data = temp->next->data; *head = temp->next->next; temp->next = NULL; temp->next = *head; return data; } intmain(){ NODE* head = NULL; int n, k, m; scanf("%d,%d,%d", &n, &k, &m); if (n < 1 || m <1 || k <1) { printf("n,m,k must bigger than 0.\n"); return0; } if (k > n) { printf("k should not bigger than n.\n"); return0; } for (int i = 1; i <= n; i++) insertNode(&head, i);//构建data为顺序的循环链表 baka(k, &head);//将head挪到第k个元素 int count=0,j, x, past = 0; for (j = 0; ; j++) { if (j == 10) { putchar('\n'); j = 0; } x = cirno(m, &head); if (x == past) break; elseif (j == 0) ; else putchar(' '); printf("%d",x );//从头节点遍历到第m个,再改变头节点 count++; past = x; } if(count==0||count%10!=0) putchar('\n'); freeList(head); return0; }
2024.09.18
展开查看
约瑟夫问题是一个经典的问题,我们不妨将这个经典问题进行扩展,变成一个双向的约瑟夫问题。
已知 n 个人(不妨分别以编号 1,2,3,…,n 代表 )围坐在一张圆桌周围,首先从编号为 k 的人从 1 开始顺时针报数,1, 2, 3, …,记下顺时针数到 m 的那个人,同时从编号为 k 的人开始逆时针报数,1, 2, 3, …,数到 m 后,两个人同时出列。然后从出列的下一个人又从 1 开始继续进行双向报数,数到 m 的那两个人同时出列,…;。依此重复下去,直到圆桌周围的人全部出列。直到圆桌周围只剩一个人为止。