约瑟夫环问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围,每个人手里都有一个密码。玩家随机输入一个初始密码m,从编号为k的人开始报数,数到m的那个人出列,并将其手中的密码视为m;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围人全部出列。
新学了单循环链表的操作,简单写了一下约瑟夫环,有不对的地方还望大神指出。
代码如下:
#include#include typedef struct node { int sequence, password;//玩家的序号和密码 struct node* next; }Node,*List; struct node* link_create(int n); void play(Node* head, int n, int k, int m); void link_print(Node* head,int n); int main() { Node* head; int n = 0,k=0,m=0;//n为玩家人数,k为起始位置,m为初始密码 printf("请输入玩家人数n"); scanf_s("%d", &n); printf("请输入开始计数的位置n"); scanf_s("%d", &k); printf("请输入初始密码n"); scanf_s("%d", &m); head = link_create(n);//创建一个长度为n的链表 link_print(head, n); play(head, n, k, m); } struct node* link_create(int n) { List p=NULL,q=NULL,head; head = (List)malloc(sizeof(Node));//创建一个链表的表头 p = head; if (n != 0) { for (int i = 1; i <= n; i++)//通过循环进行链表结点的插入,实现初始化 { int password = 0; q = (List)malloc(sizeof(Node)); q->sequence = i; printf("请输入序号为%d的密码n",q->sequence); scanf_s("%d", &password); q->password = password; p->next = q; p = q; } q->next = head->next;//初始化完毕后,将尾节点指向头结点的下一位 free(head);//头结点内没有存储数据,因此将该头结点释放 head = NULL;//防止野指针 } return q->next;//返回新的头结点 } void play(Node* head, int n, int k, int m) { //用两个指针来进行删除操作 List p = head; Node* r = head->next; if (k != 1)//链表第一个元素的标号就是1,这里不要和数组元素的下标混为一谈 { for (int i = 1; i < k; i++) { p = r; r = r->next; } } while (n--) { for (int j = 1; j < m - 1; j++) { p = r; r = r->next; } printf("->%d", r->sequence); p->next = r->next; m = r->password;//将出列的玩家的密码设为新的密码 free(r); p = p->next; r = p->next; } printf("n"); } void link_print(Node* head,int n) { Node* p = head; for (int i = 1; i <= n; i++) { printf("(%d,%d) ", p->sequence,p->password); p = p->next; } printf("n"); }



