[] Data structures and respectively LinkList chain sequence table SeqList solve the problem Josephus

Josephus problem

Josephus problem is described as follows:
set number 1,2,3,4, ..., n of the n individuals sitting in a circle, the agreed number is k (1 <= k <= n) from a human numbered off, the number of m to that of a personal column, and from 1 to start the next several reported that the number of individuals in and out of the m columns, and so on, until everyone out of the line up, thereby creating a team out of sequence numbers, please the output of this sequence.

LinkList list and sequence table SeqList

Lists and tables are linear sequence table, the sequence table is a linear table in order of logical elements stored in a set of consecutive addresses in the memory cell, and the list is a linear list elements strung together by the pointer, list not adjacent elements in the adjacent memory cell, in other words having a logical order between adjacent list elements stored without physical address of a neighbor.
And implement specific list of sequential table before, see this article:

[] Data structure implemented in Java classes SeqList sequence table
[] data structure implemented in Java objectlist LinkList

Personal recommendations look at the table to look at the order of the list.

Josephus Problem Analysis

The key to solve this problem is to make the data connected end to end, when traversing to the end of the array when the next element should be the first part. If a sequence table, then traversed to the end of the data when the index is reset to zero. If you use a list of words, just want the tail pointer pointing to the head, will become a single-chain circular list.
Dequeue operation will be relatively simple, a case where the list is only necessary in the front of an element dequeue pointer to a rear element to a force element, in the case where the sequence table, remove the function call, the dequeue element removal, and let the whole element behind a forward unit.
Termination sequence table should the conditions when the sequence is terminated table is empty, because with each dequeue operation, the order of elements in the table will be reduced by one. Termination condition list traversal is terminated when the pointer is empty.

Code

Analysis of the key points above, we next step is to use the code to achieve the above logic, the first is to achieve sequential table:

package DS;

import java.util.Scanner;

/*
 * SeqList API介绍
 * setIncr(int inc): 设置顺序表每次增加时增量的大小
 * setCapacity(int newSize): 设置新的最大容量
 * getCapacity(): 获取数组的最大容量
 * size(): 获取顺序表已经存放数据的数量,同length()
 * get(int i): 获取顺序表下标为i的元素值
 * set(int i,T x): 修改下标值为i的元素值,即为修改data[i]
 * indexOf(int begin,int end,T value): 在begin和end之间查找值为value的元素下标值,使用顺序查找法
 * indexOf(T o): 在整个线性表中查找元素o的下标值
 * indexOf(int begin,T o): 在下标为begin到末尾的线性表中查找元素o的下标值
 * add(int i,T x): 在i位置插入数据元素x
 * add(T x): 在表尾添加数据元素x
 * append(T x): 在表尾添加数据元素x
 * addSort(T x): 以有序方式向顺序表中插入数据元素x
 * sort(): 对顺序表从小到大排序
 * remove(int i): 删除下标为i的元素,并返回被删除的元素
 * remove(T value): 删除值为value的元素,并返回被删除的元素
 * clear(): 清除整个顺序表
 * toString(): 将顺序表转化成字符串,便于直接输出顺序表
 * toArray(): 将顺序表转化成Object数组,并返回
 * toArray(T[] a): 将顺序表转换为类型为E的数组
 * iterator(): 返回一个迭代对象
 * length(): 获取线性表长度
 * isEmpty(): 判断线性表是否为空
 */

public class Josephus_Seq {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int n, k, m;
		System.out.print("请输入n,k,m的值:");
		n = scan.nextInt();
		k = scan.nextInt();
		m = scan.nextInt();
		// 定义一个顺序表代表这组人,1表示这个人还未出队,最初都是未出队状态
		SeqList<Integer> seqList = new SeqList<Integer>();
		for (int i = 0; i < n; i++)
			seqList.add(i);
		// 因为顺序表是从0开始到n-1的,而题之中给的的k是从1到n的,所以将k-1付给k
		k--;
		int flag = 0, i = k;
		while (!seqList.isEmpty()) {
			flag++;
			if (flag == m) {
				//如果要将当前元素移除,i的值就不用变,因为移除后seqList中元素整体向前平移一个单位
				System.out.print((seqList.get(i) + 1) + " ");//输出出队编号,从1到n
				seqList.remove(i);
				if(seqList.isEmpty())
					break;
				flag = 0;
			}
			else {
				//如果这个元素不动,则需要i++来访问下一个元素
				i++;
			}
			if (i >= seqList.length)
				i = 0;
		}
	}
}

List implementation:

package DS;

import java.util.Scanner;

/*
 * LinkList API介绍
 * 
 * LinkList(): 构造函数
 * clear(): 删除整个列表
 * removeAll(): 删除整个列表,调用clear函数来实现
 * getNode(int i): 获得逻辑上i号节点
 * get(int i): 获得逻辑上i号节点的值
 * set(int i,T x): 修改i号节点的值
 * add(int i,T x): 将值为x的节点插入到i号位置
 * add(T key): 在链表尾部插入元素key
 * addBack(T key): 在链表尾部插入元素key,和add(T key)函数的作用一样
 * addFront(T key): 在链表首部插入元素key
 * remove(int i): 删除i号节点,并返回i号节点对应的值
 * remove(): 重载remove,删除头节点
 * removeFront(): 删除链表头节点,与remove()函数同义
 * removeBack(): 删除链表尾节点
 * addSort(T value): 将值value按从小到大的排序方式插入链表
 * sort(): 对链表按照从小到大的顺序进行排序
 * indexOf(int begin,int end,T key): 在索引begin和end之间查找值key,返回逻辑编号
 * search(T key): 功能同indexOf,遍历整个链表,一般不使用,主要用于实现字典
 * contains(T key): 判断链表中是否存在值为key节点
 * toString(): 将链表中的值转换成字符串
 * toArray(): 将链表转换成Object数组
 * toArray(E[] a): 将单链表转化为特定类型的数组,使用了函数泛型
 * iterator(): 返回迭代器对象
 */

public class Josephus_Link {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int n, k, m;
		System.out.print("请输入n,k,m的值:");
		n = scan.nextInt();
		k = scan.nextInt();
		m = scan.nextInt();
		// 实例化LinkList对象来存储队伍信息
		LinkList<Integer> linkList = new LinkList<Integer>();
		// 初始化链表
		for (int i = 0; i < n; i++) {
			linkList.add(i);
		}
		// 将链表首位相连
		linkList.last.next = linkList.first;
		k--;
		int flag = 0;
		Lnode<Integer> pLnode = linkList.getNode(k);
		Lnode<Integer> qLnode = linkList.getNode(0);
		// System.out.print(linkList.first.data);
		while (pLnode != null) {
			flag++;
			if (flag == m) {
				System.out.print((pLnode.data + 1) + " ");
				// 获取pLnode前一个节点qLnode
				while (qLnode.next != pLnode) {
					qLnode = qLnode.next;
				}
				qLnode.next = pLnode.next;
				pLnode.next = null;
				pLnode = qLnode.next;
				flag = 0;
			} else {
				pLnode = pLnode.next;
			}
		}
	}
}

发布了61 篇原创文章 · 获赞 16 · 访问量 1万+

Guess you like

Origin blog.csdn.net/qq_41427568/article/details/89681131