当前位置:网站首页>Circular linked list---------Joseph problem
Circular linked list---------Joseph problem
2022-08-02 03:39:00 【Xiaoru wants to sleep】
环形链表---------约瑟夫问题
单向环形链表
约瑟夫问题:设编号为1,2,……………….,n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,以此类推,直到所有人出列为止,由此产生一个出队编号的序列.
思路:
- The creation of the first node ,让first指向该节点,And to form a ring
- 后面当我们每创建一个新的节点,就把该节点,加入到已有的环形链表中,将最后一个节点的next指向第一个节点
根据用户的输入,生成一个小孩出圈的顺序
需要创建一个辅助指针(变量)helper,It should point to the last node of the circular linked list in advance
Before the child counts,让first和helper指针移动k-1 次,Moved from which a child begin to count off position
当小孩报数时,让first和helper指针同时移动m-1次
这时就可以将first指向的小孩节点出圈
first = first.next;
helper.next = first
原来first指向的节点就没有任何引用,就会被垃圾回收机制回收
package com.xiaoru.linkedlist;
public class Josepfu {
public static void main(String[] args) {
//测试一下,Look at the building circular linked list and traversal is correct
CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
circleSingleLinkedList.addBoy(25);
circleSingleLinkedList.showBoy();
//测试一下,Child ones are correct
circleSingleLinkedList.countBoy(1, 2, 25);
}
}
//创建一个环形的单向链表
class CircleSingleLinkedList{
//创建一个first节点,先不赋值,Do not set the current number
private Boy first = new Boy(-1);
//添加小孩节点,构建成一个环形的链表
public void addBoy(int nums) {
//numsdo a check
if (nums<1) {
//At least one child
System.out.println("nums的值不正确");
return;
}
Boy curBoy = null;//辅助指针,帮助构建环形链表
//使用for来创建我们的环形链表
for (int i = 1; i <= nums; i++) {
//Create child nodes based on labels
Boy boy = new Boy(i);
//如果是第一个小孩
if (i==1) {
first = boy;
first.setNext(first); //构成环
curBoy = first;//让curBoy指向第一个小孩
}else {
curBoy.setNext(boy);
boy.setNext(first);
curBoy = boy;
}
}
}
//Traverse the current circular linked list
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();
}
}
/** * @param startNo 表示从第几个小孩开始数数 * @param countNum 表示数几下 * @param nums 表示最初有多少小孩在圈中 * * */
//根据用户的输入,计算出小孩出圈的顺序
public void countBoy(int startNo , int countNum,int nums) {
//先对数据进行校验
if (first == null || startNo<1 ||startNo>nums) {
System.out.println("参数输入有误,请重新输入");
return;
}
//创建要给辅助指针,帮助完成小孩出圈
Boy helper = first;
//需要创建一个辅助指针(变量)helper ,事先应该指向环形链表的最后这个节点
while(true) {
if (helper.getNext() == first) {
//说明helper 指向最后小孩节点
break;
}
helper = helper.getNext();
}
//小孩报数前,先让first 和helper移动k-1次
for (int j = 0; j < startNo -1 ; j++) {
first = first.getNext();
helper = helper.getNext();
}
//当小孩报数时,让first和helper指针同时移动 m-1次,然后出圈
while (true) {
if (helper == first ) {
//There is only one person in the circle
break;
}
//让first和helper指针同时移动countnum -1
for (int i = 0; i < countNum-1; i++) {
first = first.getNext();
helper = helper.getNext();
}
//这时first指向的节点,就是要出圈的节点
System.out.printf("小孩%d出圈\n",first.getNo());
//这时将first指向的小孩节点出圈
first = first.getNext();
helper.setNext(first);
}
System.out.printf("最后留在圈中的小孩编号%d\n",helper.getNo());
}
}
//创建一个boy类,表示一个节点
class Boy {
private int no;//编号
private Boy next;
//构造方法
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;
}
}
边栏推荐
猜你喜欢
随机推荐
解决MySQL创建子视图并查看的时候,字符集报错问题
亚马逊卖家怎么提升转化率
小程序 van-cell 换行能左对齐问题
Dynamic proxy tool class
String comparison size in MySQL (date string comparison problem)
The usage of json type field in mysql
js 数组去重的常用方法
相对路径和绝对路径
第一篇博客
PCL—点云数据分割
AttributeError: ‘Upsample‘ object has no attribute ‘recompute_scale_factor‘
由中序遍历和前序遍历得到后序遍历(树的遍历)
知识问答与知识会话的区别
Cut out web icons through PS 2021
The difference between the knowledge question and answer session with the knowledge
Amazon sellers how to improve the conversion
跨域问题解决
排序学习笔记(二)堆排序
钟表刻度线
利用 nucleo stm32 f767zi 进行USART+DMA+PWM输入模式 CUBE配置