Data structure -- one-way ring linked list | Joseph problem

Posted by jlambert on Wed, 19 Jan 2022 10:14:41 +0100

The origin of Joseph's problem, let's tell a little story first

It is said that the famous Jewish historian Josephus had the following story: after the Romans occupied jotapat, 39 Jews hid in a cave with Josephus and his friends. 39 Jews decided that they would rather die than be caught by the enemy, so they decided a way of suicide. 41 people lined up in a circle, counting from the first person. Every time they counted to the third person, they had to commit suicide, Then count off again from the next until everyone commits suicide. However, Josephus and his friends did not want to comply. Start with one person, cross the k-2 person (because the first person has been crossed), and kill the K person. Then, he crossed the k-1 man and killed the k-th man. This process continues along the circle until there is only one person left, and the person can continue to live. The question is, given and, where to stand in the first place to avoid execution. Josephus asked his friend to pretend to obey first. He arranged his friend and himself in the 16th and 31st positions, so he escaped the death game.

In short, the so-called Joseph problem is that n people form a circle, count from the person with the specified number from 1, count to m, his next count from 1, count to m, and so on until everyone is listed.
Tips

A one-way circular linked list without leading nodes is used to deal with Joseph's problem. First, a one-way circular linked list with n nodes is formed, and then count from 1 from node i. when m is counted, the corresponding node is deleted from the linked list, and then continue the above operation from the next node of the deleted node until the last node is deleted from the linked list

First create a Person node
//Create a Person class to represent a node
public class Person {
    private int no;//number
    private Person next;//Point to the next node, which is null by default

    public Person(int no) {
        this.no = no;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public Person getNext() {
        return next;
    }

    public void setNext(Person next) {
        this.next = next;
    }
}
To create a one-way circular linked list:
//Create a circular one-way linked list
public class CircleSingleLinkedList {
    //First create a first node
    private Person first = null;

    /**
     * Add nodes to build a circular linked list
     *
     * @param nums Number of nodes in the current linked list
     */
    public void addBoy(int nums) {
        //nums does a data check
        if (nums < 1) {
            System.out.println("Wrong value!");
            return;
        }
        //Create auxiliary nodes to help build a ring linked list
        Person curPerson = null;
        //Use the for loop to create a ring linked list
        for (int i = 1; i <= nums; i++) {
            //Add nodes by number
            Person person = new Person(i);
            //Judge whether it is the first node
            if (i == 1) {
                first = person;
                first.setNext(first);//Form a ring
                curPerson = first;//Let curPerson point to the first node
            } else {
                curPerson.setNext(person);//Point the next node of the current node to the newly added node
                person.setNext(first);//Point the next node of the newly added node to the first node to form a ring again
                curPerson = person;//Move secondary node back
            }
        }
    }

    /**
     * According to the user's input, the order of circles is calculated
     *
     * @param startNo  Number of nodes from
     * @param countNum Count
     * @param nums     The number of nodes in the linked list needs to be verified
     */
    public void countBoy(int startNo, int countNum, int nums) {
        //Check the data first
        if (first == null || startNo < 1 || startNo > nums) {
            System.out.println("Wrong input!");
            return;
        }
        //Create an auxiliary node to complete the circle out task
        Person helper = first;
        //When the while loop is out, the auxiliary node helper points to the last node
        while (true) {
            //When the next node of the auxiliary node points to the first node, it means that the auxiliary node points to the last node
            if (helper.getNext() == first) {
                break;
            }
            helper = helper.getNext();//Move the secondary node backward
        }
        //Move the first and helper startNo - 1 times before counting
        for (int i = 0; i < startNo - 1; i++) {
            first = first.getNext();//At this point, first points to the node that starts to report the number
            helper = helper.getNext();//At this point, the helper points to the previous node of the node that started reporting
        }
        //When counting, let the first and helper move countNum - 1 at the same time, and then circle (here is a circular operation until there is still one node in the linked list)
        System.out.print("The order of turning out the circle is:");
        while (true) {
            if (helper == first) { // Indicates that there is only one node in the circle
                break;
            }
            for (int i = 0; i < countNum - 1; i++) {
                first = first.getNext();
                helper = helper.getNext();
            }
            //At this time, the node pointed to by first is the node to be circled
            System.out.print(first.getNo() + "->");
            //At this time, the node pointed to by first is circled
            first = first.getNext();
            helper.setNext(first);
        }
        System.out.print(+ first.getNo());
    }

    //Traverse the current circular linked list
    public void showList() {
        //Determine whether the linked list is empty
        if (first == null) {
            System.out.println("The linked list is empty!");
            return;
        }
        //Create a secondary node to help complete the traversal
        Person curPerson = first;
        System.out.print("The order of the linked list is:");
        while (true) {
            //If the next node of the current node points to first, the traversal is completed
            if (curPerson.getNext() == first) {
                System.out.print(curPerson.getNo());
                break;
            }
            System.out.print(curPerson.getNo()+"->");
            curPerson = curPerson.getNext();//Move the current node back
        }
        System.out.println();
    }
}
The test code is as follows:
public class CircleSingleLinkedListTest {

    public static void main(String[] args) {
        CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
        circleSingleLinkedList.addBoy(5);//Add 5 nodes
        circleSingleLinkedList.showList();//Print the circular linked list
        circleSingleLinkedList.countBoy(2,3,5);//Start counting from the second node and count one node every three times. There are 5 nodes in the linked list.
    }
}

Topics: Java data structure linked list