One way circular list and java implementation of Joseph problem

Posted by lorri on Mon, 20 Jan 2020 03:38:27 +0100

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());
	}
	

Published 6 original articles, won 1 praise and 795 visitors
Private letter follow

Topics: Mobile