题目大意
编号为1,2,3.....n的n个人按顺时针方向围成一圈,每个人手上都有一个秘密,开始时选择一个数作为报数的上限m,从第一个人开始从1开始报数报到m停止,报到m的那个人出列,将他手中的密码重新作为报数的上限,这样循环下去,问最后一个数是什么
【解析】
这个经典题的话其实就是可以用一个循环链表的方式解决,我们先创建一个链表,之后不断的插入数据,最后将q->next=list其实q->next是尾结点了,将list代表的头结点又给了尾结点所以构成了循环的链表,需要注意的是怎么删除一个元素,需要有一个指针指向它的前一个结点,这样的话比如p是需要删除的结点,q->next=p->next;有了这个之后我们就可以放心的free(p)了。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct node{
int number; /*编号*/
int psw; /*个人密码*/
struct node *next;
} LNode,*LinkList;
void insertList(LinkList *list,LinkList q,int e1,int e2){
LinkList p;
p=( LinkList)malloc(sizeof(LNode));
p->number = e1;
p->psw = e2;
if(!*list){
*list=p;
p->next=NULL;//如果是第一个节点
}
else{
p->next=q->next;//插入节点
q->next=p;
}
}
void CreatJoseph(LinkList &jsp , int n)
{
LinkList q = NULL , list = NULL;
int i , e2;
for(i=0;i<n;i++){
scanf("%d",&e2);
insertList(&list,q,i+1,e2); /*向q指向的结点后面插入新的结点*/
if(i == 0) q = list; /*第一次之生成头结点,q也指向头结点*/
else q = q->next; /*q指向下一结点*/
}
q->next = list; /*形成循环链表*/
jsp = list; //返回
}
void facs(LinkList &jsp, int m)
{
LinkList p ,q;
int i;
q = p = jsp ;
while(q->next != p) q=q->next; /*q指向p的前一个结点*/
printf("The order of a column is\n") ;
while(p->next != p){
for(i=0;i<m-1;i++)
{ /*p指向要删除的结点,q指向p的前一个结点*/
q = p;
p = p->next;
}
q->next = p->next;
printf("%d ",p->number);
m = p->psw;
free(p);
p = q->next;
}
printf("\nThe last person in the circle is %d\n",p->number); /*打印出最后留在队中的人的编号*/
}
int main()
{
LinkList jsp;
int n , m;
scanf("%d",&n) ;
CreatJoseph(jsp, n);
scanf("%d",&m) ;
facs(jsp,m) ;
return 0;
}