Joseph环
joseph环是对于循环链表的应用,分为三部分:创建循环链表、应用规则、组装
typedef struct node{
/* data */
int No; /*游戏者的编号*/
unsigned int Pwd; /*游戏者的密码*/
struct node *next;
}Node,*LinkList;
创建循环链表
LinkList creat_list(int n){
LinkList p,r;//p创建的结点 r未知
int i;
p=(Node*)malloc(sizeof(Node));//申请空间
if(!p) return NULL;//创建头结点失败
scanf("%d",&(p->Pwd));//输入第一个结点的值
if(p->Pwd<=0) return NULL;//判断输入的值是否符合规则
p->No=1; //第一个的编号为1
p->next=p; //形成单环 p的下一个结点是本身
r=p;//将r结点变为环的最后一个结点
/*创建之后的结点*/
for (i=2;i<=n;i++){
/* code */
p=(Node*)malloc(sizeof(Node));//申请空间
if(!p) return NULL;//创建头结点失败
scanf("%d",&(p->Pwd));//输入第i个结点的值
p->No=i;//第i个的编号为i
//尾插法
p->next=r->next;//改变上一个结点的环 新建立的p的next变成r.next形成新环
r->next=p;//将r和p连接起来
r=p;//将r变为最后一个结点
}
return r;
}
应用规则
void playing(LinkList tail,int n,int m){
LinkList pre,p;
if(m<=0) return;
int k;
m=m%n;//目标值 决定第几个人出场
pre=tail;//pre结点为头结点的上一个结点
p=tail->next;//p结点为头结点
k=1;
while(n>1){
if(k==m){
printf("%4d",p->No);//找到的话 输出p的编号值
pre->next=p->next;//然后删除p结点
n--;//减少总共玩的人数
m=p->Pwd%n?p->Pwd%n:n;//然后看这个p结点的Pwd为多少 假如p.Pwd==n的话 选择n不选择0
free(p);//释放p结点
p=pre->next;//将p结点重置为头结点
k=1;//继续从新的第一个头结点开始重复
}
else{
k++;//没找到的话 下一个人
pre=p;//头结点的前置结点变为头结点
p=p->next;//头结点变成下一个结点
}
}
printf("%4d",p->No);
}
组装
int main(void){
LinkList tail;
int n,it;
scanf("%d %d",&n,&it);//输入几个结点和第一个的目标值
tail=creat_list(n);
if(tail){
playing(tail,n,it);
}
return 0;
}