约瑟夫问题
约瑟夫问题介绍
约瑟夫问题是典型的单向环形链表的应用
下图来自尚硅谷韩顺平老师《数据结构与算法》课件:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pl6T1oYS-1589164343318)(C:\Users\18221\AppData\Roaming\Typora\typora-user-images\image-20200511101253132.png)]
代码
节点类的构建
class Boy{
private int no;
private Boy next=null;
public Boy(int no){
this.no=no;
}
}
自成环算法
主要的思路其实就是用一个cur作为增长链表的指针,增长后,尾部节点还应指向first,然后移动cur指针,也就是说cur指针永远指向尾节点,而first永远是头节点。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-46ybaeIq-1589164343321)(C:\Users\18221\AppData\Roaming\Typora\typora-user-images\image-20200511103123401.png)]
private Boy first=null;
public void addBoys(int nums){
if(nums<1){
System.out.println("值错误");
return;
}
Boy curBoy=null;
for(int i=0;i<nums;i++){
Boy boy=new Boy(i);
if(nums==1){
first=boy;
first.next=first;
curBoy=first;
}else{
curBoy.next=boy;
boy.next=first;
curBoy=boy;
}
}
}
出圈算法
出圈算法的关键其实就是链表节点的删除,链表节点的删除需要一个指针指向要删除节点的前一个节点,先将当前节点移动到后面的节点,然后前节点的next指针指向它就ok了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r5OqdCU1-1589164343322)(C:\Users\18221\AppData\Roaming\Typora\typora-user-images\image-20200511103108260.png)]
public void countBoy(int startNo,int countNums,int nums){
if(first==null || startNo<1||startNo>nums){
System.out.println("参数有误");
return;
}
Boy helper=first;
while(helper.next!=first){
helper=helper.next;
}
for(int i=0;i<startNo;i++){
first=first.no;
helper=helper.next;
}
while(true){
if(helper==first)
break;
for(int i=0;i<countNums;i++){
first=first.next;
helper=helper.next;
}
System.out.printd("小孩%d出圈\n",first.no);
first=first.next;
helper.next=first;
}
}
\n",first.no);
first=first.next;
helper.next=first;
}
}