#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
/**
*@Name:Josephus环轮流报数问题
*@Description:
* 问题描述:
* 设有n个人围坐在一个圆桌周围,现从第s个人开始报数,数到第m的人出列,然后从出列
* 的下一个人重新开始报数,数到第m的人又出列...如此反复直到所有的人全部出列为止。
* 问题:对于任意给定的n,s和m,求出按出列次序得到的n个人员的序列。
*
* 解决方案:循环链表
* 1、创建一个包含n个结点的循环链表模拟n个人玩轮流报数出局游戏(1,2,3,.....n)。
* 2、从当前结点出发,每隔一定的数量(游戏设定的出局数)删除一个结点,只到剩下最后一个结点。
* 3、最后一个结点就是所要求解的游戏前的那个人的编号。
*@Author:Freedoman
*@Date: 2014-8-6
*/
struct Node {
int data;
struct Node * next;
};
typedef struct Node * PNode;
/*-------游戏准备:创建包含n个结点的循环链表---------*/
PNode createCirLinkedList(int n){
PNode head = NULL,p = NULL,temp;
int i;
for(i = 0; i < n; i ++){
// 第1个结点
if(i == 0){
temp = (PNode)malloc(sizeof(head));
head = temp;
p = head;
temp->data = i+1;
temp->next = head;
}else{
// 以后的结点
temp = (PNode)malloc(sizeof(head));
temp->data = i + 1;
temp->next = head;
p->next = temp;
p = temp;
}
}
return head;
}
/*-----------从头结点出发查找第s个结点--------*/
PNode findElement(PNode head,int s){
PNode p = head;
int i;
for(i = 2; i<= s; i++){
p = p->next;
}
return p;
}
/*-----------游戏开始:迭代删除结点-------------*/
int deleteElement(PNode head,int m){
PNode p = head;
int i;
while(p != p->next){
// 轮流报数,p迭代到要出局的前一个结点
for(i = 0; i < m-2; i++){
p = p->next;
}
// 打印下一个要出局的数字
printf("出局>>>>%d\n",p->next->data);
// 出局(删除结点)
p->next = p->next->next;
// 迭代进入下一轮
p = p->next;
continue;
}
// 打印出最一个剩余的
printf("出局>>>>%d\n",p->data);
return 0;
}
/*-------打印当前循环链表-----------------*/
void printCirLinkedList(PNode head){
PNode p = head;
printf("打印[");
do{
printf(" %d ",p->data);
p = p->next;
}while(p != head);
printf(" %d ",p->data);
printf("]\n");
}
int main(){
int n,s,m;
printf("请输入参与者个数n >>>");
scanf("%d",&n);
printf("请输入起始编号s >>>");
scanf("%d",&s);
printf("请输入间隔m >>>");
scanf("%d",&m);
PNode head = createCirLinkedList(n);
printCirLinkedList(head);
findElement(head,s);
deleteElement(head,m);
return 0;
}
循环链表解决Josephus环轮流报数问题
最新推荐文章于 2020-04-12 15:27:12 发布