约瑟夫问题 java实现单向环形链表解决
问题:设编号1.2.3.—n;围成一圈,约定由K个人从1开始报数,数到m那个人出列,出列位置的下一个人又开始从1报数,数到m又出列。直到所有人出列,产生一个出列的编号序列。
思路:不带头节点的单向环形链表,n个节点,k节点开始从1计数,记到m,删除该节点。再从删除节点下一个位置开始计数,直到最后一个节点从链表中删除、
(韩顺平老师网课跟练笔记)
创建单向环形链表
class CircleSingleLinkedLit{
//创建first节点,当前没编号
private Boy first=new Boy(-1);
//添加小孩节点,构建成环形链表
public void addBoy(int nums) {
//nums校验
if(nums<1) {
System.out.println("nums不正确");
return;
}
Boy curBoy=null; //辅助指针,帮助构建环形
//循环创建环形链表
for(int i=1;i<=nums;i++) {
//根据编号创建小孩节点
Boy boy=new Boy(i);
if(i==1) {
first=boy;
first.setNext(first); //构成环状
curBoy=first; //first不能动,让cur指向第一个小孩
}else {
curBoy.setNext(boy);
boy.setNext(first);
curBoy=boy;
}
}
}
创建Boy类,一个类对象表示一个节点
class Boy{
private int no; //编号
private Boy next; //指向下一个节点,默认null
public Boy(int no) {
this.no=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;
}
}
遍历链表
public void showBoy() {
if(first==null) {
System.out.println("没有小孩哟");
return;
}
//因为first不能动,因此定义辅助指针完成遍历
Boy curBoy=first;
while(true) {
System.out.printf("小孩的编号 %d \n",curBoy.getNo());
if(curBoy.getNext()==first) {
break;
}
curBoy=curBoy.getNext(); //指针后移
}
}
出圈函数代码,根据用户输入条件,输出出列编号
//根据输入,计算出小孩的出圈顺序
/* startNo表示从第几个小孩开始
* countnum 表示数几下 nums 表示小孩总数
*/
public void countBoy(int startNo,int countNum,int nums) {
if(first==null||startNo<1 || startNo>nums) {
System.out.println("参数输入有误");
return;
}
//才创建辅助指针,帮助小孩出拳
Boy help=first;
//需求创建一个辅助指针help,事先指向环形链表最后个节点
while(true) {
if(help.getNext()==first) { //这是help指针到最后了
break;
}
help=help.getNext();
}
//小孩报数前,先让first和help 移动k-1次
for(int j=0;j<startNo-1;j++) {
first=first.getNext();
help=help.getNext();
}
//当小孩报数时,让fist和help指针同时移动 m-1次,然后出圈。循环出圈,直到只剩一个节点
while(true) {
if(help==first) { //只剩一人
break;
}
//让first 和help 指针同时移动count-1次,然后小孩出圈
for(int j=0;j<countNum-1;j++) {
first=first.getNext();
help=help.getNext();
}
//first 节点的小孩就是要出圈的小孩
System.out.printf("小孩%d出圈\n",first.getNo());
first=first.getNext();
help.setNext(first); //help指向上一句更新的新first
}
System.out.printf("最后留在圈中的小孩编号%d",first.getNo());
}
测试代码
public class Josepfu {
public static void main(String[] args) {
CircleSingleLinkedLit circleSingleLinkedLit = new CircleSingleLinkedLit();
circleSingleLinkedLit.addBoy(5);
circleSingleLinkedLit.showBoy();
System.out.println();
//测试
circleSingleLinkedLit.countBoy(2, 3, 5); // 4>2>1>3>5
}
}
leSingleLinkedLit.showBoy();
System.out.println();
//测试
circleSingleLinkedLit.countBoy(2, 3, 5); // 4>2>1>3>5
}
}
![运行展示](https://img-blog.csdnimg.cn/db1d3ae8128c49b99d72d7c88a9a4f4f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Yqq5Yqb5ZCR5LiK55qE6YOR5ZCM5a2m,size_9,color_FFFFFF,t_70,g_se,x_16#pic_center)