/***************************************************************
*约瑟夫环问题
*问题描述:N个人做成一圈,从第K个人开始报数游戏(从0开始报数),
报M的出列,最后剩下的一个人获胜
*算法: 循环单链表(无头节点)
*新建单链表: 返回value最小的节点当作"head",新建过程即是插入过程
*删除(出列操作): 记录前驱,方便删除
*author:fangchang
*time: 2016/04/04 18:25
****************************************************************/
#include<stdio.h>
#include<stdlib.h>
#define N 5 //N个人,环长
#define M 1 //M次传递后,删除当前人
#define K 2 //从第K个人开始游戏
typedef struct node {
int value;
struct node * next;
}*pnode;
typedef pnode circleList;
circleList createCircleList();
void answer();
int main() {
answer();
fflush(stdin);
getc(stdin);
return 0;
}
void answer() {
circleList clist = createCircleList();
int j=0;
circleList cur=clist;
while(cur->value!=K) {
cur = cur->next; //寻找游戏起点(K)
}
circleList pre=clist;
while(pre->next!=cur) { //寻找游戏起点人的前驱
pre=pre->next;
}
//以下是core code
while(pre->next!=pre) { //循环终止条件
while(j<M) { //查找应该被删除的节点
pre=cur;
cur=cur->next;
++j;
}
pre->next=cur->next; //开始删除节点
printf("delete %d\n",cur->value);
free(cur);
cur=pre->next;
j=0;
}
//以上是core code
printf("The winner is %d\n",pre->value);
}
circleList createCircleList() { //新建循环单链表,无头指针
int i;
circleList cur,pre;
circleList firstNode;
for(i=0;i<N;++i) {
cur=(circleList)malloc(sizeof(struct node));
if(!cur) {
return NULL;
}
cur->value=i+1;
cur->next=cur; //单节点循环
if(i==0) { //返回value最小的节点当作"head"
firstNode = cur;
pre=cur;
}
else { //插入
cur->next = pre->next;
pre->next=cur;
pre=cur;
}
}
return firstNode;
}