约瑟夫问题(有时也称为约瑟夫置换,是一个出现在计算机科学和数学中的问题。在计算机编程的算法中,类似问题又称为约瑟夫环。又称“丢手绢问题”。)
约瑟夫问题是个有名的问题:指定一个数M,N个人围成一圈,从第一个开始报数,第M个将出列,然后下一个人又从1开始报数,到M那个人又出列,直到剩下最后一个,其余人都将出列。例如N=6,M=5,则出列的顺序是:5,4,6,2,3,1。
这道题我们使用链式存储和顺序存储两种方式实现。链式存储的数据结构是链表,不懂的可以去看看数据结构的书,顺序存储就用普通的数组即可,下面放代码。
import java.util.Scanner;
public class Joseph {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int m,n;
System.out.println("输入报数号");
m=in.nextInt();
System.out.println("输入个数");
n=in.nextInt();
//.................链式结构
Linkedlist l=new Linkedlist();
for(int i=0;i<n;i++) {
l.add(i+1);
}
l.link();
System.out.print("链式存储结果为");
for(int i=0;i<n;i++) {
System.out.print(l.out(m));
}
System.out.println();
//................顺序结构
int x=0;
Queue q=new Queue(n);
int num[]=new int[n+1];
for(int i=0;i<n+1;i++) {
num[i]=i;
}
for(int i=1;i<=n;i++) {
for(int j=0;j<m;j++) {
x=x+1>n?(x+1)%n:x+1;
while(num[x]==0) {
x=x+1>n?(x+1)%n:x+1;
}
}
q.push(num[x]);
num[x]=0;
}
System.out.print("顺序存储结果为");
for(int i=0;i<8;i++) {
System.out.print(q.pop());
}
}
}
class Linkedlist{//链表存储
int size,x;
Node h,r,t;
public Linkedlist() {
size=0;
h=r=t=null;
}
class Node{
int value;
Node link;
public Node(int x) {
value=x;
}
}
public void add(int x){
Node newHead=new Node(x);
if(size==0){
h=r=t=newHead;
}else{
r.link=newHead;
r=newHead;
}
size++;
}
public void link() {
r.link=h;
}
public int out(int m) {
for(int i=0;i<m-1;i++) {
r=r.link;
}
x=r.link.value;
r.link=r.link.link;
return x;
}
}
class Queue{//顺序存储
private int f,r,N;
int q[];
public Queue(int N) {
this.N=N;
f=r=0;
q=new int[N];
}
public void push(int x) {
q[r++]=x;
}
public int pop() {
return q[(f++)%N];
}
}