这是一道经典的链表题
约瑟夫环–自杀环问题
约瑟夫环问题有着这样的历史:
Josephus有过的故事:39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓。于是决定了自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀。然后下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
大致意思
一共有N个人围坐在一起, 循环周期是M, 第一个人报数1, 第二个人报数2, 当报数到M时, 这个人就会出列。 下一个人继续从1开始报数, 整个过程持续到所有人出列为止。 这种问题一般会问最后一个出列的人是谁, 或者问你某个人是第几个出列的。。。
对于学习了计算机的我们来说,重复性如此强的过程,当然要交给计算机来帮我们完成呐。所以我们一起来编写这个程序吧。
之前更了数组实现和数学推理方法,现在来补链表法。
大致思路
建立一个单向循环链表(看题目而定),先建立一个表头,在把每个人一个一个的尾插进去,然后把头尾相连。在模拟报数,把要自杀的人一个一个删掉,最后留下来的那个,就是答案。
#include<stdio.h>
#include<stdlib.h>
typedef struct node{
int data;
struct node *next;
} node;
node* creat(int data)
{
node *head;
head = (node *)malloc(sizeof(node));
head->data = data;
head->next = NULL;
return head;
}
//建立链表
node* creatnode(node* head, int data)
{
node *now = head;
node *neww = (node*)malloc(sizeof(node));
neww->data = data;
neww->next = NULL;
while(NULL != now->next)
now = now->next;
now->next = neww;
return neww;
}
//插入节点
void merge(node* head, node* end)
{
end->next = head;
}
//首尾相连
void detele(node* qian, node* need){
qian->next = need->next;
free(need);
}
//删除节点
int main()
{
node *head = creat(1);
node *end;
node *now = head;
int n, m, i, j;//n表示有多少个人,m表示报到几就自杀。
scanf("%d%d", &n, &m);
for(i=2;i<=n;i++)
end = creatnode(head, i);
merge(head, end);
node *qian = end;
for(i=1;i<n;i++)
{
for(j=1;j<m;j++)
{
now = now->next;
qian = qian->next;
}
if(i!=(n-1)){
detele(qian, now);
now = qian->next;
}
}
printf("%d", qian->data);
return 0;
}
谢谢观看!数组模拟实现和数学推理法在这里!