循环单向链表解决约瑟夫问题

约瑟夫问题

男孩类

class Boy{
	private int no;
	private Boy next;
	public Boy(int no){
		this.setNo(no);
	}
	public int getNo() {
		return no;
	}
	public void setNo(int no) {
		this.no = no;
	}
	public Boy getNext() {
		return next;
	}
	public void setNext(Boy next) {
		this.next = next;
	}
}

定义头节点

class CircleSingleLinkList {
	private Boy first = null;

添加小孩

public void addBoy(int nums){
		if(nums<1){
			System.out.println("数据不正确");
			return;
		}
		Boy cusBoy = null;
		for(int i = 1;i<=nums;i++){
			Boy boy =new Boy(i);
			if(i==1){
				first = boy;
				boy.setNext(first);
				cusBoy = first;
			}
			else{
				cusBoy.setNext(boy);
				boy.setNext(first);
				cusBoy = boy;
				
			}
		}
	}

显示

//显示
	public void showBoy(){
		if(first == null){
			System.out.println("链表为空");
			return;
		}
		Boy cusBoy = first;
		while(true){
			//打印
			System.out.println("Boy-编号:"+cusBoy.getNo());
			//判断是否到达尾部,退出
			if(cusBoy.getNext() == first){
				break;
			}
			//后移
			cusBoy = cusBoy.getNext();
		}
	}

出圈算法

//淘汰
	public void countBoy(int startNo,int countNo,int nums){
		//校验
		//startNo  开始节点
		//countNo  跳转的次数
		if(first == null||startNo<1||startNo>nums){
			System.out.println("参数错误");
			return;
		}
		//辅助指针
		Boy helper = first;
		while(true){
			//让helper。next指向first
			if(helper.getNext() == first){
				break;
			}
			helper = helper.getNext();
		}
			//报数之前,跳转到开始报数的位置
			for(int j=0;j<startNo-1;j++){
				first = first.getNext();
				helper = helper.getNext();
			}
			//不断出圈,直到只剩一个小孩
			while(true){
				//出圈条件,first = helper
				if(helper == first){ 
					break;
				}
				for(int j = 0;j<countNo-1;j++){
					first = first.getNext();
					helper = helper.getNext();
				}
				System.out.println("出圈:"+first.getNo());
				first = first.getNext();
				helper.setNext(first);
			}
			System.out.println("-----------------");
			System.out.println("最后的小孩为:"+helper.getNo());
		}

全部代码

package linkedList;

public class Josepfu {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		CircleSingleLinkList list = new CircleSingleLinkList();
		list.addBoy(1000);
		list.showBoy();
		list.countBoy(1, 9, 1000);
	}

}
class CircleSingleLinkList {
	private Boy first = null;
	public void addBoy(int nums){
		if(nums<1){
			System.out.println("数据不正确");
			return;
		}
		Boy cusBoy = null;
		for(int i = 1;i<=nums;i++){
			Boy boy =new Boy(i);
			if(i==1){
				first = boy;
				boy.setNext(first);
				cusBoy = first;
			}
			else{
				cusBoy.setNext(boy);
				boy.setNext(first);
				cusBoy = boy;
				
			}
		}
	}
	//显示
	public void showBoy(){
		if(first == null){
			System.out.println("链表为空");
			return;
		}
		Boy cusBoy = first;
		while(true){
			//打印
			System.out.println("Boy-编号:"+cusBoy.getNo());
			//判断是否到达尾部,退出
			if(cusBoy.getNext() == first){
				break;
			}
			//后移
			cusBoy = cusBoy.getNext();
		}
	}
	//淘汰
	public void countBoy(int startNo,int countNo,int nums){
		//校验
		//startNo  开始节点
		//countNo  跳转的次数
		if(first == null||startNo<1||startNo>nums){
			System.out.println("参数错误");
			return;
		}
		//辅助指针
		Boy helper = first;
		while(true){
			//让helper。next指向first
			if(helper.getNext() == first){
				break;
			}
			helper = helper.getNext();
		}
			//报数之前,跳转到开始报数的位置
			for(int j=0;j<startNo-1;j++){
				first = first.getNext();
				helper = helper.getNext();
			}
			//不断出圈,直到只剩一个小孩
			while(true){
				//出圈条件,first = helper
				if(helper == first){ 
					break;
				}
				for(int j = 0;j<countNo-1;j++){
					first = first.getNext();
					helper = helper.getNext();
				}
				System.out.println("出圈:"+first.getNo());
				first = first.getNext();
				helper.setNext(first);
			}
			System.out.println("-----------------");
			System.out.println("最后的小孩为:"+helper.getNo());
		}
	}
class Boy{
	private int no;
	private Boy next;
	public Boy(int no){
		this.setNo(no);
	}
	public int getNo() {
		return no;
	}
	public void setNo(int no) {
		this.no = no;
	}
	public Boy getNext() {
		return next;
	}
	public void setNext(Boy next) {
		this.next = next;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值