/*
* 问题描述:
* 编号为1,2,...,n 的n 个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。
* 一开始任选一个正整数作为报数上限值 m,从第一个人开始。按顺时针方向自 1 开始顺序报数,报到m 时停止报数。
* 报m的人出列,将他的密码作为新的m 值, 从他在顺时针方向上的下一个人开始重新从1 报数,如此下去,直至所有人全部出列为止。
*/
/*
* 思路分析:
* 1、将人的顺序编号,从1到n
* 2、将人的编号存到结点的num域
* 3、将人的密码存到结点的pas域
* 4、构造一个带头结点的循环链表,解决首尾相连的问题
* 5、开始报数,从头报数,报到m的人出局,释放该结点。直到人数只有一个人时,退出循环。输出获胜的人。
*/
//
// Created by Admin on 2017/3/30.
//
#include <cstdio>
#include <malloc.h>
//定义结点
typedef struct node{
int num;
int pas;
struct node *next;
}JosephNode;
typedef JosephNode *CircularList;
//初始化循环链表为空表
void InitList(CircularList &first){
first=(JosephNode *)malloc(sizeof(JosephNode));
first->next=first;
}
//存储每个人的编号和密码
void InputData(CircularList &first,int n){
int temp;
printf("请输入每个人的密码(以空格分隔):");
CircularList newnode,p=first;
for (int i = 1; i <= n; ++i) {
scanf("%d",&temp);
newnode=(JosephNode *)malloc(sizeof(JosephNode)); //创建结点
if(!newnode)exit(0);
newnode->num=i; //存储编号
newnode->pas=temp; //存储出局密码
//插入到链尾
p->next=newnode;
p=newnode;
}
p->next=first; //将链尾连接头结点
}
//遍历链表
void TravelList(CircularList first){
CircularList p=first->next;
while(p!=first){
printf("\tnum: %d\t\tpas: %d\n",p->num,p->pas);
p=p->next;
}
}//testing
//solve
void Solve(CircularList &first,int n,int m){
CircularList p=first;
int count=1; //count用于控制输出格式
while (n--){
int i=1; //i为计数器
while(i<m){ //找到第m-1个结点
if(p->next==first)p=p->next; //如果下一个结点为头结点,则跳过头结点,计数器不自增
else{ //否则计数+1,并且指向下一个结点
p=p->next;
i++;
}
}//循环结束后,p为第m-1个结点
if(p->next==first)p=p->next; //判断下一个是否为头结点,是则跳过头结点
printf("num= %d\t",p->next->num); //输出第m个结点的标号
if(n==0)printf("\n\n\tThe Winner is : %d",p->next->num);
else{
if(count%5==0)printf("\n");
count++;
}
m=p->next->pas; //更新m值
//删除第m个结点
CircularList q=p->next;
p->next=q->next;
free(q);
}
printf("\n\n");
}
int main(){
char op;
int n,m;
CircularList first;
printf("输入Y/y进入操作!\n");
while (~scanf("%c",&op)){
if(op=='n'||op=='N')break;
else{
system("cls");
InitList(first);
printf("请输入参与人数:");
scanf("%d",&n);
printf("请输入初始出局密码:");
scanf("%d",&m);
InputData(first,n);
printf("\n/****************testing*****************/\n");
printf("/****************数据存储****************/\n");
TravelList(first);
printf("\n/****************出列顺序****************/\n");
Solve(first,n,m);
}
printf("输入Y/N,继续操作:\n");
getchar();
}
return 0;
}
特殊数据已测试