约瑟夫环问题求解

约瑟夫问题java语言解法

Josephu 问题为:设编号为 1,2,… n 的 n 个人围坐一圈,约定编号为 k(1<=k<=n)的人从 1 开始报数,数到 m 的那个人出列,它的下一位又从 1 开始报数,数到 m 的那个人又出列,依次类推,直到所有人出列为止,由此 产生一个出队编号的序列。

提示 :用一个不带头结点的循环链表来处理 Josephu 问题:先构成一个有 n 个结点的单循环链表,然后由 k 结点起从 1 开 始计数,计到 m 时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从 1 开始计数,直到最后一个结点从链表中删除算法结束。

循环链表解决

//节点定义 
class Node{
	int data;
	Node next;
	public Node(int data) {
		this.data=data;
	}
}
//问题处理
class Xunhuan_list{
	Node first=null;
	public void CreatNode(int t) {//创建一个 节点为i的循环链表
		Node temp=null;
		for(int i=1;i<=t;i++)
		{
			Node node=new Node(i);
			if(i==1)
			{
				first=node;
				first.next=first;
				temp=first;
			}else {
				temp.next=node;
				node.next=first;
				temp=node;
			}
		}
		}
	public void printAll() {//遍历全部的节点
		Node temp=first;
		do {
			System.out.print(temp.data);
			if(temp.data!=5)
				System.out.print("->");
			if(temp.data==5)
			System.out.println();
			temp=temp.next;
		}while(temp!=first);
	}

	public void Josepfu(int start,int num)//约瑟夫问题解决方案
	{
		Node helper=first;
		while(helper.next!=first)//这里最开始出现的问题是  因为将helper!=first  所以导致helper 和 first 重合
			{
			helper=helper.next;//将协同指针指向在循环链表的最后一个节点上,也就是first的后面
			}
		for(int i=0;i<start-1;i++)//将两个指针同时移到起点和起点前
		{
			first=first.next;
			helper=helper.next;
			
		}
		while(first!=helper)
		{
			for(int i=0;i<num-1;i++)
			{
				first=first.next;
				helper=helper.next;
			}
			System.out.println("这次要去死的人是"+first.data);
			first=first.next;
			helper.next=first;
		}
		System.out.println("最后的幸存者为"+first.data);
	}
}
  • 下面利用主方法测试一下 总人数为5 人 每数到3就去死
public class Main {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Xunhuan_list list=new Xunhuan_list();
		list.CreatNode(5);
		list.printAll();
		list.Josepfu(1, 3);  //这里输入的数据为  1 为从什么位置开始  3 是每叫到几就去死
	}

}

运行结果如下
在这里插入图片描述
问题总结

  1. 关于循环链表的创建思路。
  2. 约瑟夫问题的解决算法
    1.先创建一个helper 指针 ,将此指针指向first指针的前一个节点
    然后 (如果是从第一个节点开始 那么就指向最后一个节点),每次数数m就跳跃m-1次,然后将first指针移动到出圈节点的下一个节点,然后将helper的next指针指向first,这样就实行了出圈,以此类推。

                             ———————————————这将会是很好的一生!
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值