环形单链表解决约瑟夫问题

环形单向链表解决约瑟夫问题:
在这里插入图片描述

首先要创建一个N个小孩的环形单向链表:
    1.创建一个first指针,置为空,再创建一个辅助指针curBoy
    2.用for循环创建小孩节点,如果是第一个节点(first指向第一个小孩,并且第一个小孩的next域指向自己,再让辅助指针curBoy指向第一个小孩)
    3.用for循环创建小孩节点,如果是第一个节点后的节点(首先让curBoy的next域指向当前小孩,再让当前小孩的next域指向first,最后让辅助指针移动到当前小孩上)
    4.重复3,直到所有小孩都加完
环形单向链表创建好后,接下来就是小孩出圈:
    1.创建一个help指针,让它位于first所在的第一个节点的前一个节点,之后help指针一直都是跟着first指针移动的
    2.从第K个小孩开始报数,那么,first指针应该移动到第K个小孩上,help指针应该跟着移动到first指针的后一个节点上
    3.开始报数,first指针移动M-1个节点,help也移动M-1个节点
    4.第三步中first所在的小孩节点出圈(先让first后移到下一个节点,再让help所在的小孩节点的next域指向first移动后的节点)
    5.重复第3、4步,直到first与help指针重合就结束,最后剩下的那个小孩就是first和help指针所在的那个小孩节点

代码:
小孩节点类

/**
 * 小孩节点类
 * @author codewen
 *
 */

public class Boy {

	private int bNo;//小孩编号
	Boy next;//下一个男孩
	
	public Boy() {
	}
	public Boy(int bNo) {
		this.bNo = bNo;
	}
	public int getbNo() {
		return bNo;
	}
	public void setbNo(int bNo) {
		this.bNo = bNo;
	}
	public Boy getNext() {
		return next;
	}
	public void setNext(Boy next) {
		this.next = next;
	}
	@Override
	public String toString() {
		return "Boy [bNo=" + bNo + "]";
	}
}
import org.junit.Test;

/**
 * 约瑟夫问题
 * @author codewen
 *
 */

public class JosephTest {

	private Boy first = null;//创建第一个节点指针用于标记第一个节点
	
	//增加节点的方法
	public void addBoy(int boyNum) {
		if(boyNum < 1) {
			System.out.println("男孩个数不符合要求,无法增加节点");
			return;
		}
		Boy curBoy = null;//创建一个辅助指针
		for(int i=1; i<=boyNum; i++) {
			Boy boy = new Boy(i);
			if(i == 1) {//如果是第一个男孩
				//让first指针指向第一个男孩
				first = boy;
				//让第一个男孩next域指向自己 形成环形
				boy.next = boy;
				//让辅助指针指向第一个男孩
				curBoy = boy;
			}else {//如果不是第一个男孩
				curBoy.next = boy;
				//让男孩的next域指向头节点 形成环形
				boy.next = first;
				//辅助指针后移
				curBoy = curBoy.next;
			}
		}
	}
	
	//显示节点的方法
	public void queryBoy() {
		if(first == null) {
			System.out.println("该环形链表为空,无法显示");
			return;
		}
		Boy curBoy = first;//辅助指针
		while(true) {
			System.out.println(curBoy);
			if(curBoy.next == first) {
				break;
			}
			curBoy = curBoy.next;
		}
	}
	
	//小孩出圈的方法 有N个小孩,从第K个开始报数,数到M的小孩出圈
	public void outBoy(int N, int K, int M) {
		if(K < 1 && K > N) {
			System.out.printf("总共%d个小孩,不能从第%d个小孩开始报数\n", N, K);
			return;
		}
		if(M < 1) {
			System.out.println("M不能小于1");
			return;
		}
		//1.创建环形单向链表
		addBoy(N);
		//2.创建一个help指针,让它位于first所在的第一个节点的前一个节点,之后help指针一直都是跟着first指针移动的
		Boy help = first;
		for(int i=0; i<N-1; i++) {
			help = help.next;
		}
		//2.从第K个小孩开始报数,那么,first指针应该移动到第K个小孩上,help指针应该跟着移动到first指针的后一个节点上
		for(int i=0; i<K-1; i++) {
			first = first.next;
			help = help.next;
		}
		//5.重复第3、4步,直到first与help指针重合就结束,最后剩下的那个小孩就是first和help指针所在的那个小孩节点
		while(help != first) {
			//3.开始报数,first指针移动M-1个节点,help也移动M-1个节点
			for(int i=0; i<M-1; i++) {
				first = first.next;
				help = help.next;
			}
			//4.第三步中first所在的小孩节点出圈(先让first后移一个节点,再让help所在的小孩节点的next域指向first移动后的节点)
			System.out.println("出圈的小孩为:"+first);//或者help(此时help与first相等)
			first = first.next;
			help.next = first;
		}
		System.out.println("最后剩下的小孩为:"+first);
	}
	
	@Test
	public void test1() {
		//addBoy(5);
		//queryBoy();
		outBoy(5, 1, 2);
	}
}

结果:
在这里插入图片描述

发布了30 篇原创文章 · 获赞 8 · 访问量 1382

猜你喜欢

转载自blog.csdn.net/qq_43598193/article/details/104061629