约瑟夫问题
问题一:
#include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node *next; } ListNode; typedef ListNode *LinkList; LinkList initRing(int n,LinkList R); LinkList DeleteDeath(int n,int k,LinkList R); int main() { LinkList R; int n,k; printf("总人数n="); scanf("%d",&n); printf("报数上限k="); scanf("%d",&k); R=initRing(n,R); R=DeleteDeath(n,k,R); } /* 建立单循环链表 */ LinkList initRing(int n,LinkList R) { ListNode *p,*q; int i; R=(ListNode *)malloc(sizeof(ListNode));//把R当做头结点,里面没有数据值 q=R;//q为临时变量,将头节点赋值给q for (i=1;i<=n;i++) { p=(ListNode *)malloc(sizeof(ListNode));//给p分配空间 p->data=i;//初始化p的data q->next=p;//q是p的上一节点,将q指向p首地址 q=p;//此时p为尾节点,将p赋值给临时变量q } p->next=R->next;//使最后一个结点指向第一个结点,构成一个循环。 return R; } LinkList DeleteDeath(int n,int k,LinkList R) { int i,j; ListNode *p,*q; p=R; for(i=1;i<n;i++)//n代表循环n次结束,全部死亡 { for(j=1;j<k;j++){ p=p->next;//p是第k-1个 (待删除项) } q=p->next; p->next=q->next; printf("%d ",q->data); free(q); R=p; } printf("存活下来的是%d",R->data); return R; }
加入可以规定从何处开始报数的功能:
#include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node *next; } ListNode; typedef ListNode *LinkList; LinkList initRing(int n,LinkList R); LinkList DeleteDeath(int n,int k,LinkList R); int main() { LinkList R; int n,k; printf("总人数n="); scanf("%d",&n); printf("报数上限k="); scanf("%d",&k); R=initRing(n,R); R=DeleteDeath(n,k,R); } /* 建立单循环链表 */ LinkList initRing(int n,LinkList R) { ListNode *p,*q; int i; R=(ListNode *)malloc(sizeof(ListNode));//把R当做头结点,里面没有数据值 q=R;//q为临时变量,将头节点赋值给q for (i=1;i<=n;i++) { p=(ListNode *)malloc(sizeof(ListNode));//给p分配空间 p->data=i;//初始化p的data q->next=p;//q是p的上一节点,将q指向p首地址 q=p;//此时p为尾节点,将p赋值给临时变量q } p->next=R->next;//使最后一个结点指向第一个结点,构成一个循环。 return R; } LinkList DeleteDeath(int n,int k,LinkList R) { int i,j,m; //由于不支持一个函数有过多传入的参数,且新建链表时用不着起始位置,故我们把起始位置放在函数中定义和使用 printf("输入开始报数的位置m:"); scanf("%d",&m); ListNode *p,*q; p=R; for(j=0;j<m;j++)//先将当前位置向后移动m位,即表示从第m个开始报数 { p=p->next; } for(i=1;i<n;i++)//n代表循环n次结束,全部死亡 { for(j=1;j<k;j++) { p=p->next;//p是第k个 (待删除项) } q=p->next;//q指向p下一节点 p->next=q->next;//p下一节点指向q下一节点(即为空) printf("%d ",q->data);//输出此即将被删除的节点的值 free(q);//释放该节点空间 R=p;//下一轮初始位置位p(0位置) } printf("存活下来的是%d",R->data);//上面循环了n-1次,1人存活,R(即为此时的p)为最后存活者 return R;//返回存活者R节点 }
C语言生成不重复的随机数
#include <stdio.h> #include <stdlib.h> #include <time.h> int main() { int n; printf("请输入n值:"); scanf("%d",&n) ; int list[n], i,j, a; srand(time(NULL));//设置随机数种子。 for(i = 0; i < n; i ++) { while(1) { a = rand()%10; //获取一个0~10之间的随机数。 for(j = 0; j < i; j ++) if(list[j] == a) break;//检查重复,有重复则跳出此步,且不满足下一步的条件,故而该重复值没有被储存下来,并且重新随机取值。 if(j == i)//没有重复值,保存到list中。 { list[i] = a; break; } } } for(i = 0; i < n; i ++)//打印获取到的随机数序列。 printf("%d,",list[i]); printf(" "); return 0; }