问题描述:约瑟夫环问题的一种描述是:编号为1,2,...,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。试设计一个程序求出出列顺序。
基本要求:利用单向循环链表模拟此过程,按照出列的顺序印出各人的编号。
本人完成这道题的时候,用了两种方法,一种是创建了一个结点Node类,然后在main方法里面写;另一种则从题目要考察的角度,另创建了一个循环单链表的类。
下面-----艰辛的调试过程,一开始作为菜鸡,概念都很模糊,历经了两天的。。崩溃。。终于调试正确!!!
while(head!=null){
for(int i=1;i<=m-2;i++){
head=head.next;
}
int out=head.next.data1;
m=head.next.data2;
System.out.printf("%d\t",out);
head.next=head.next.next;
}
一开始,写了这样
一个死循环,把电脑卡死了。当最后只有一个或两个元素的时候,永远都无法满足head!=null
后面只要就是运算结果总有问题。还有符号写错的问题,,被自己蠢哭 @-@
教训:
首先,在设变量名的时候,那些比较相像的,比如p ,q ,一定要注意,不要写反了。
然后,把一个结点用“=”赋值给另一个结点时,比如 Node head=L.head ,当后面的操作让L.head 改变时,head是没有改变的,一开始我以为是在别的方法里面对head的改变,不能影响在main 方法的head的值,但对Java进行理解并测试之后, 像这种 结点类的对象,传递给方法时,传递的是引用,即指针的指向,所以我一开始的猜想是错的,我真正的错误在于,我写了Node head=L.head 这条语句之后,在后面对链表进行一些操作后,L.head变了,但我在main的循环是对head操作的,这里的head是原来赋值时的head,而不是L.head,而我却以为可以用赋值之后的head代替L.head
public static Node createlist(int n){
Scanner sc=new Scanner(System.in);
System.out.println("请分别输入各人的密码");
int code=sc.nextInt();
Node head=new Node(1,code);
Node p=head;
for(int a=2;a<=n;a++){
p=p.next;
code=sc.nextInt();
p=new Node(2,code);
}
p.next=head;
return head;
}
用这种方法是无法创建以head为第一个结点的链表的
因为,在一开始,head.next=null;那么 p=head.next;就相当于p==null;而之后p再怎么新建或往后连结点,都与head无关了。
所以这样也是错误的建表方式。
下面附上我的两种方法吧
方法1:
package 链表;
import java.util.Scanner;
public class yueSeFuRing {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
//用户设置一个m的初始值
System.out.println("请设置一个m的初始值");
int m=sc.nextInt();
System.out.println("请输入人数n的值(n<=30):");
int n=sc.nextInt();
System.out.println("请分别输入各人的密码");//3 1 7 2 4 8 4
int code=sc.nextInt(); //正确的出列顺序应为6,1,4,7,2,3,5
Node head=new Node(1,code);
Node p=head;
for(int a=2;a<=n;a++){
code=sc.nextInt();
head.next=new Node(a,code);
head=head.next;
}
head.next=p;
head=p;
//游戏中
Node out;
while(head!=head.next&&head!=null){
Node p1=head;
Node t=p1;
for(int i=1;i<m;i++){
t=p1;
p1=p1.next;
}
out=p1;
if(out==head){
while(p1.next!=head){
p1=p1.next;
}//循环完之后,p1.next=head
p1.next=p1.next.next;
head=p1.next;
}
int out1=out.data1;
m=out.data2;
System.out.printf("%d\t",out1);
t.next=out.next;
head=t.next;
}
System.out.print(head.data1);
}
}
class Node{
public int data1;
public int data2;
public Node next;
public Node(){
this(0,0,null);
}
public Node(int data1,int data2) {
this(data1,data2,null);
}
public Node(int data1,int data2, Node next) {
this.data1=data1;
this.data2=data2;
this.next=next;
}
}
方法2:
package 数据结构;
import java.util.Scanner;
public class ring {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
//用户设置一个m的初始值
System.out.println("请设置一个m的初始值");
int m=sc.nextInt();
System.out.println("请输入人数n的值(n<=30):");
int n=sc.nextInt();
//
list L=new list(n);
Node head=L.head;
Node out;
while(L.head!=L.head.next&&head!=null){
Node p=L.head;
for(int i=1;i<m;i++){
p=p.next;
}
out=p;
int out1=out.data1;
m=out.data2;
System.out.printf("%d\t",out1);
L.delect(p);
}
System.out.print(L.head.data1);
}
}
class list{
Scanner sc=new Scanner(System.in);
static Node head;
//创建一个循环单链表
public list(){
head=new Node();
}
public list(int n){
System.out.println("请分别输入各人的密码");//3 1 7 2 4 8 4
int code=sc.nextInt(); //正确的出列顺序应为6,1,4,7,2,3,5
head=new Node(1,code);
Node p=head;
for(int a=2;a<=n;a++){
code=sc.nextInt();
head.next=new Node(a,code);
head=head.next;
}
head.next=p;
head=p;
}
//求长度
public int len(){
Node p=head;
if(head==null)
return 0;
else
{
int i;
for(i=1;p.next!=head;i++){
p=p.next;
}
return i;
}
}
//判断是否空表
public boolean isEmpty(){
return head==null;
}
//删除
void delect(Node p){
if(len()==1){
head=null;
}
else{
if(p==head){
while(p.next!=head){
p=p.next;
}//循环完之后,p.next=head
p.next=p.next.next;
head=p.next;
}
else{
Node q=head;
while(q.next!=p){
q=q.next;
}
q.next=q.next.next;
head=q.next;
}//之后head为被删除元素的下一下元素
}
}
}
class Node{
public int data1;
public int data2;
public Node next;
public Node(){
this(0,0,null);
}
public Node(int data1,int data2) {
this(data1,data2,null);
}
public Node(int data1,int data2, Node next) {
this.data1=data1;
this.data2=data2;
this.next=next;
}
}