用C链表实现约瑟夫环问题
问题:设有n个人围成一个圆圈,现从第s个人开始报数,数到第m的人出列,然后从出列的下一个人重新开始报数,数到第m的人再次出列,如此反复,直到所有的人全部出列为止。对于任意给定的n、s、m,求按出列次序得到的n个人员的序列。
例:
图片就是问题简单示例,里面是每次要循环的数据,后面的S是出列的人
思路:
- 先创建一个链表,链表的长度就是n
- 从第s个节点开始循环
- 判断是否是第m个数
- 如果是第m个数,就输出并删除当前节点
- 循环到最后一个节点,再从第一个节点接着循环
主要代码:
1 void yuesefu (LinkList * head, int n, int s, int m) 2 { 3 LinkList * p, * r, * q; 4 int i = 1, j = n, k, l; 5 p = GetData_LinkList(head, s); //从第S位开始 6 7 //判断是否循环完成 8 while (j > 0) { 9 //判断是否为第m个数 10 if (i == m) { 11 i = 0; 12 //输出这轮出局的人 13 printf("%d\n", p->data); 14 //存储当前节点的值 15 k = p->data; 16 17 //删除当前节点 18 q = head->next; 19 l=1; 20 while (q != NULL) { 21 //判断当前节点得值是否等于要删除的值 22 if (q->data == k) { 23 //删除节点 24 DeleteNode_LinkList(head, l); 25 break; 26 } 27 l++; 28 q = q->next; 29 } 30 //从下一个节点开始循环 31 p = GetData_LinkList(head, l); 32 j--; 33 }else { 34 p = p->next; 35 } 36 //如果超出链表长度,再从第一个节点开始循环 37 if (p == NULL) 38 p = head->next; 39 40 i++; 41 } 42 43 }
整体代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 typedef int elemtype; 5 6 typedef struct node 7 { 8 elemtype data; 9 struct node * next; 10 }LinkList; 11 12 //创建链表 13 LinkList * Create_LinkListF(int n) 14 { 15 int i; 16 LinkList * head, * p; 17 head = (LinkList *) malloc (sizeof(LinkList)); 18 19 if (head == NULL) 20 return head; 21 22 head->next = NULL; 23 24 for (i=1; i<=n; i++) { 25 p = (LinkList *) malloc (sizeof(LinkList)); 26 27 if (p == NULL) 28 return head; 29 30 p->data = i; 31 p->next = head->next; 32 head->next = p; 33 } 34 35 return head; 36 } 37 38 //按序号查找 39 LinkList * GetData_LinkList (LinkList * head, int i) 40 { 41 LinkList * p; 42 int j = 0; 43 44 if (i <= 0) 45 return NULL; 46 47 p = head; 48 49 while (p->next != NULL && j<i) { 50 p = p->next; 51 j++; 52 } 53 54 if (i == j) 55 return p; 56 else 57 return NULL; 58 } 59 60 //删除节点 61 int DeleteNode_LinkList (LinkList * head, int i) 62 { 63 LinkList * p, * r; 64 65 if (i <= 0) 66 p = NULL; 67 else 68 if (i == 1) 69 p = head; 70 else 71 p = GetData_LinkList(head, i-1); 72 73 if (p == NULL) { 74 return 0; 75 }else { 76 r = p->next; 77 if (r == NULL) 78 return 0; 79 80 p->next = r->next; 81 free(r); 82 return 1; 83 } 84 85 } 86 87 void yuesefu (LinkList * head, int n, int s, int m) 88 { 89 LinkList * p, * r, * q; 90 int i = 1, j = n, k, l; 91 p = GetData_LinkList(head, s); //从第S位开始 92 93 //判断是否循环完成 94 while (j > 0) { 95 //判断是否为第m个数 96 if (i == m) { 97 i = 0; 98 //输出这轮出局的人 99 printf("%d\n", p->data); 100 //存储当前节点的值 101 k = p->data; 102 103 //删除当前节点 104 q = head->next; 105 l=1; 106 while (q != NULL) { 107 //判断当前节点得值是否等于要删除的值 108 if (q->data == k) { 109 //删除节点 110 DeleteNode_LinkList(head, l); 111 break; 112 } 113 l++; 114 q = q->next; 115 } 116 //从下一个节点开始循环 117 p = GetData_LinkList(head, l); 118 j--; 119 }else { 120 p = p->next; 121 } 122 //如果超出链表长度,再从第一个节点开始循环 123 if (p == NULL) 124 p = head->next; 125 126 i++; 127 } 128 129 } 130 131 int main (void) 132 { 133 int n, s, m; 134 LinkList * head; 135 136 printf("n="); 137 scanf("%d", &n); 138 139 printf("s="); 140 scanf("%d", &s); 141 142 printf("m="); 143 scanf("%d", &m); 144 145 head = Create_LinkListF(n); 146 yuesefu(head, n, s, m); 147 }

浙公网安备 33010602011771号