约瑟夫环
编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个整数作为报数上限值m,从第一个人开始顺时针自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有的人全部出列为止。试设计一个程序,求出出列顺序。
利用单向循环链表作为存储结构模拟此过程,按照出列顺序打印出各人的编号。
例如m的初值为20;n=7,7个人的密码依次是:3,1,7,2,4,8,4,出列的顺序为6,1,4,7,2,3,5。
#include<stdio.h> #include<math.h> #include<string.h> #include<stdlib.h> typedef struct Node{ int ser;//序号 int num; //密码 Node *next; }Node, *LinkList; LinkList CreateCList(int n){//创建单向循环链表 Node *pre, *rear; LinkList CL; pre = rear = CL = (Node*)malloc(sizeof(Node)); for(int i = 1; i <= n; i++){ rear->ser = i; scanf("%d", &rear->num); pre->next = rear; pre = rear; rear = (Node *)malloc(sizeof(Node)); } free(rear); pre->next = CL; printf("\n"); return CL; } void ShowList(LinkList CL){//展示 for(Node *p = CL; p != NULL; p = p->next){ printf("%d\n", p->num); } printf("\n"); } void Solve(LinkList CL, int m, int n){//m为初始报数上线,n为总人数 Node *p1, *p2, *t; p1 = p2 = CL; p2 = p2->next; while(p2->next != CL){//首先要找到第一个报数得前一个,以防第一次报数上线为1 p2 = p2->next; } int num = 1; while(n--){//直到n个人全部出列为止 while(num != m){ p2 = p1; p1 = p1->next; num++; } t = p1; printf("%d\n", p1->ser); p2->next = p1->next; p1 = p2->next; m = t->num; free(t); num = 1; } } int main(){ LinkList CLa; CLa = CreateCList(7); Solve(CLa,20, 7); return 0; }
种一棵树最好的时间是十年前,其次是现在。