约瑟夫环---自杀环问题 & 简单明了的循环链表版

这是一道经典的链表题

约瑟夫环–自杀环问题

约瑟夫环问题有着这样的历史:

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;
 } 

谢谢观看!数组模拟实现和数学推理法在这里!

猜你喜欢

转载自blog.csdn.net/m0_51938608/article/details/114377017