The Josephu problem is also called "the problem of losing handkerchief".
Problem Description: set n children with number 1, 2, 3, 4... In a circle. It is agreed that children with number k will start counting from 1, and children who count to m in turn will be listed. Then the next one of the listed children starts counting from 1, and the children who count to m in turn are listed, and so on, until all the children are listed, resulting in a sequence of listed numbers.
n = 5 indicates that there are 5 children; k = 1 indicates that the number is reported from the first child; m = 2 indicates that the number is 2 each time.
In this problem, a one-way ring linked list is used because the nodes need to be deleted continuously and the number of the nodes needs to be reported circularly at the same time.
First, create a node class Boy:
class Boy{ private int no ; //Child's number private Boy next ; //Point to the next node, null by default 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; } /* * The reason for setting these construction methods is that several basic properties of Boy are of private type */ }
Note: the reason why so many set and get methods are set is that several basic properties of the Boy node class are of private type. This is the usual way to get a private property.
The node class Boy is set. Next, we need to build a circular list:
Train of thought:
1. The basic operation of unidirectional circular linked list often needs three pointers: first pointer, curlboy pointer and boy pointer;
Where: the first pointer always points to the first node (either the head node or the head node) and cannot move; the boy pointer points to the new node to be added in the ring; the curlboy pointer is responsible for connecting the newly added node into the ring chain list.
2. Build process:
(1) First, create the first node (in this case, the head node) with the first pointer, and form a ring;
(2) After that, every time a new node is created with the boy pointer, the curBoy pointer is used to add the node to the existing ring list.
//Create a circular one-way linked list class CircleSingleLinkedList{ //Create a first node first, no number at present; (head) private Boy first = new Boy(-1); //Add child nodes and build a circular list public void addBoy(int nums){//Nums means to add nums children at a time //Since it is "xx", data verification must be carried out for nums (basic details) if(nums < 1 ){ System.out.println("Illegal data"); return ; } Boy curBoy = null ; //Curlboy is used as an auxiliary pointer to help build a circular linked list //Using for loop to build circular list; for(int i = 1 ; i <= nums ; i ++){ //Create child nodes based on numbers Boy boy = new Boy(i) ; //The first child is in a special situation, so special consideration should be given if(i == 1){ first = boy ; first.setNext(boy); // Attention expression curBoy = first ; } else { //The regular action of the circular single chain table curBoy.setNext(boy); boy.setNext(first); curBoy = boy ; } } } }
Note: when the first node is inserted in the linked list, it is different from other operations and needs to be discussed differently.
3. Traversal list:
(1) , first let the auxiliary pointer curloy point to the first node;
(2) , and then traverse the circular list through the while loop.
//Traverse the current circular list public void showBoy(){ //Judge whether the list is empty if(first == null) { System.out.println("The list is empty!"); return; } //Because first doesn't move, we still use a helper pointer to do the traversal Boy curBoy = first ; while(true){ System.out.printf("Child's number%d \n" , curBoy.getNo()); if(curBoy.getNext() == first){ //Description traversal completed break; } curBoy = curBoy.getNext() ; } }
The completion flag of traversal is: curloy. Getnext() = = first; because the next pointer of the last node points to the first node (or header node).
Now that the data structure has been constructed, we are going to solve the Joseph problem in detail:
According to the user's input, generate a child out of the circle order:
1. You need to create a helper pointer, which should point to the last node of the circular list in advance. (since the next field of the last node points to the first node, you need to let the helper point to the last node first, so that the helper can always follow the first pointer in the process of moving (reporting), so as to delete the node.)
Add: let the first and helper move k-1 times before the children report the number; (because the number should be reported from the k-th child)
2. When the child reports the number, let the first and helper pointer move m-1 times at the same time (the total number is m, but the first one is its own number, and the next m-1 is handed to other people);
3. At this time, you can circle the child node that first points to.
first = first.next ;
helper.next = first ;
The out of loop node just pointed to by first has no reference and will be recycled.
The specific code is as follows: (detailed analysis)
//According to the user's input, calculate the order of children's circle (Joseph problem) /** * * @param startNo Indicates the number from the first child * @param countNum How many times * @param nums How many children were in the circle at first */ public void countBoy(int startNo , int countNum , int nums){ //Verify the data first if(first == null || startNo < 1 || startNo > nums ){ System.out.println("Error in parameter input, please re-enter: "); return ; } //Create an auxiliary pointer to help children out of the circle Boy helper = first ; //You need to create a helper pointer that points to the last node of the circular list in advance //This is to keep the helper after the first in the later mobile, //The node pointed to by first will circle while(true){ if(helper.getNext() == first){//The instructions point to the last child break; } helper = helper.getNext() ; } //Let first and helper move startNo - 1 time before children report for(int j = 0 ; j < startNo - 1 ; j ++ ){ first = first.getNext() ; helper = helper.getNext() ; } //When the child reports the number, let the first and helper pointer move m-1 times at the same time, and then circle out //This is a loop operation until there is only one node in the loop while(true){ if(helper == first){ //There is only one node in the description circle break ; } //Let first and helper move countNum -1 time at the same time, and then circle one bit for(int j = 0 ; j < countNum -1 ; j ++){ first = first.getNext() ; helper = helper.getNext() ; } //At this time, the first node is the out of loop child node System.out.printf("Child%d Circle out\n" , first.getNo()); //In this case, circle the node that first points to first = first.getNext() ; helper.setNext(first); } System.out.printf("The number of the last child left in the circle is%d \n" , helper.getNo()); }