0

我正在编写一些 Java 代码,这些代码应该使用循环链接列表来实现众所周知的约瑟夫斯问题。以下是有关约瑟夫斯问题的一些信息:http ://en.wikipedia.org/wiki/Josephus_problem

我有一个学生班和司机班,它们被分配给我来创建我的约瑟夫斯班。

这是学生课程: http: //pastebin.com/4YgSA7CM

这是驱动程序类: http: //pastebin.com/Nb08Dtqk

这两个类都不能修改。

我必须从头开始制作一个 Josephus 类,该类使用有效利用 Josephus 问题的循环链表。

这是我完成的 Josephus 类,没有编译器错误:

/** Implementation of Josephus problem.  The Josephus problem
    is named after the historian Flavius Josephus.  For more
    information on this problem visit:
    http://en.wikipedia.org/wiki/Josephus_problem
  */
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.ArrayList;



public class Josephus <E> {
 private Node<E> head;
 private int count;  // number of elements in the list

 /** Constructs an empty Josephus circle */
 // Complexity O(1)
 public Josephus() {

    head = null;
    count = 0;
 }
 /** Constructs an Josephus circle by adding the
     elements from an arraylist
     @param array The ArrayList of items of type E
   */
 // Complexity: O(n)
 public Josephus(ArrayList<E> array) {
             head = null;
             for (int i = 0; i < array.size(); i++)
                     add(array.get(i));
 }


 /** Inserts the specified element in the list at the
     last position
     @param dataItem the element to add
   */
 // Complexity O(1)
 @SuppressWarnings({ "unchecked" })
    public void add(E dataItem) {

     Node <E> node = new Node <E> (dataItem, null, null);
            if (count == 0) // list is empty
                    head = node.previous= node ;


            else
               head.previous.next = node;
               node.previous = head.previous;

               head.previous = node;


            count++;
 }
         // To be completed by the student


 /** Inserts the specified element in the list at the
     end.  This method has the same behavior as add(E)
         @param dataItem the element to add at the end
       */
 // Complexity O(1)
 public void addLast(E dataItem) {
             add(dataItem);
 }

 /** Inserts the element at the beginning of the list
     @param dataItem The element to be added
   */
 // Complexity O(1)
 public void addFirst(E dataItem) {
             Node<E> node = new Node <E>(dataItem, null, null);
             // To be completed by the student

             if (head == null) // list is empty
                  head = head.previous = node;

         else {
            node.next = head;
            head.previous = node;
            head = node;
         }
         count++;
 }

 /** removes the element from the beginning of the list
     @return  The element that was remvoed
     @throws NoSuchElementException if the list is empty
   */
 // Complexity O(1)
 public E removeFirst() {
        // To be completed by the student
     if (head != null) {
                     E item = head.data;

                     if (head == head.previous) // list has only one element
                        head = head.previous = null;

                     else {  // list has more than 1 element
                        head = head.next;
                        head.previous = null;
                     }
                     count--;
                 return item;
         }
     else throw new NoSuchElementException();
     }

     /** removes the element from the end of the list
         @return  The element that was remvoed
         @throws NoSuchElementException if the list is empty
       */
      // Complexity O(1)
      public E removeLast() {
             // to be completed by the student
              if (head.previous != null) {
                            E item = head.previous.data;

                            if (head == head.previous) // list has only one item
                               head = head.previous = null;

                            else {  // list has more than one element
                                    head.previous = (head.previous).previous;
                                    head.previous.next = null;
                        }
                            count--;
                            return item;
                }
                    else throw new NoSuchElementException();
         }


     /** returns a reference to the element at
         position index
         @param index The index of the element being sought
         @return A reference to the element at position index
         @throws IndexOutOfBoundsException if index is out of range
       */
     // Complexity O(n)
     public E get(int index)  {
             if ((index < 0) || (index >= count))
                 throw new IndexOutOfBoundsException(Integer.toString(index));
             Node<E> temp = head;
             for (int i = 0; i < index; i++)
                temp = temp.next;
             return temp.data;
 }

 /** Sets the element at position index to reference
     anEntry.
     @param index The position of the element that is to
     be set
     @param anEntry The new value at position index
     @return the element that was previously at position index
     @throws IndexOutOfBoundsException if index is out of range
   */
 // Complexity O(n)
 public E set(int index, E anEntry) {
     if ((index < 0) || (index >= count))
                 throw new IndexOutOfBoundsException(Integer.toString(index));
             Node<E> temp = head;
             for (int i = 0; i < index; i++)
                temp = temp.next;
             E result = temp.data;
             temp.data = anEntry;
             return result;
 }

 /** Inserts the specified element in the list at a
     given index
     @param index The position at which the new element
     has to be inserted
     @param anEntry The element to add
     @throws IndexOutOfBoundsException if index is out of range
   */
     // Complexity O(n)
     public void add(int index, E anEntry) {
             // To be completed by the student
               if ((index < 0) || (index > count))
                       throw new IndexOutOfBoundsException(Integer.toString(index));

               if (index == 0) addFirst(anEntry);
               else if (index == count) addLast(anEntry);
               else {

                       Node <E> node = head;
                       int i = 0;
                       while(node!=null && i<index){                 
                               i++;
                               node = node.next;
                       }
                   Node<E> newNode = new Node <E> (anEntry, node, node.next);
                   node.next.previous = newNode;
                   node.next = newNode;
                   count++;
           }
     }

     /** searches for target and returns the position of the
         first occurrence, or -1 if it is not in the list
         @param target The element we are searching for
         @return The position of target if found; -1 if not found
       */
     // Complexity O(n)
     public int indexOf(E target) {
             Node<E> temp = head;
             for (int i = 0; i < count; i++) {
                     if (temp.data.equals(target)) return i;
                     temp = temp.next;
         }
         return -1;
 }

 /** removes the element at position index
         @param index The index of the element to be removed
         @return The element that was removed
         @throws IndexOutOfBoundsException if index is invalid
       */
     // Complexity O(n)
     public E remove(int index) {
        // to be completed by the student
             if ((index < 0) || (index >= count))
                        throw new IndexOutOfBoundsException(Integer.toString(index));
             Node<E> temp = head;
             for(int i =0;i<index; i++)
                     temp = temp.next;
                 E result = temp.data;
                 temp.next = temp.previous;
                 return result;



 }

 /** sets the start position for the Josephus game
     @param index The starting position
     @throws IndexOutOfBoundsException if index is invalid
   */
 // Complexity O(n)
 public void setStartPosition(int index) {
             if ((index < 0) || (index >= count))
                throw new IndexOutOfBoundsException(Integer.toString(index));

             for (int i = 0; i < index; i++)
                 head = head.next;
 }

 /* This private utility method is used in startJosephus
    method.
    Complexity O(1)
  */
 private void removeAfter(Node<E> node) {
             node.next = node.next.next;
             node.next.previous = node;
             count--;
 }

 /** simulates the Josephus game by killing every other person
     until the winner is the only one left.
     @return The survivor of the game
   */
 public E startJosephus() {
     E item =head.data;
     if(head.next != null){
             if(head == head.previous)
                     return item;

             else
                     while(count>1);
            removeAfter(head);
            head =head.next;
 }
     return item;



     }


 /** Returns a list-iterator of the elements in this list
    (in proper sequence), starting at the beginning
    of the list.
  */
public ListIterator <E> iterator() {
       return new myIterator();
}

/** @return The number of elements in the list
  */
public int size() {
            return count;
}

// this is an inner clss implementing the ListIterator
// interface.
// visit http://docs.oracle.com/javase/1.4.2/docs/api/java/util/ListIterator.html
// for a complete list of methods in ListIterator

private class myIterator implements ListIterator <E> {
        private Node<E> forward = head;
        private Node<E> backward = head;
        private boolean firstTime = true;

        /** checks if a current item E  is the last
            in the collection
          */
        public boolean hasNext() {
            return (forward != null);
        }

        /** returns the next item in the collection if
           there is one.  If there is no more items
           throws NoSuchElementException
          */
        public E next() {
               if (forward == null) throw
                            new NoSuchElementException();
               else {
                       E item = forward.data;
                       forward = forward.next;
                       if (forward == head) forward = null;
                       return item;
               }
         }

         /** checks if a current item is the first
                 in the collection
           */
         public boolean hasPrevious() {
                 return (backward != null);
         }

         /** returns the previous item in the collection if
                 there is one.  If there is no more items
                 throws NoSuchElementException
           */
         public E previous() {
                 if (backward == null) throw
                        new NoSuchElementException();
                 else {
                        if (firstTime) {
                                    backward = backward.previous;
                                    firstTime = false;
                             }
                            E item = backward.data;
                        backward = backward.previous;
                        if (backward == head.previous) backward = null;
                        return item;
                 }
      }

          /* this operation is not supported */
          public void add(E obj) {
                    throw new UnsupportedOperationException();
          }

          /* this operation is not supported */
          public void set(E obj) {
                    throw new UnsupportedOperationException();
          }

          /* this operation is not supported */
          public int previousIndex() {
                  throw new UnsupportedOperationException();
          }

          /* this operation is not supported */
          public int nextIndex() {
                  throw new UnsupportedOperationException();
          }

          /* this operation is not supported */
          public void remove() {
                  throw new UnsupportedOperationException();
          }
}

private static class Node <E> {
    private E data;
    private Node<E> next;
    private Node<E> previous;

   /** constructor Creates an empty node with both next and
       previous fields set to be null
       @param dataItem - item to be inserted
     */
   private Node(E dataItem) {
       data= dataItem;
       previous = next = null;
   }

   /** creates a new node that references another node
       @param dataItem The data stored
       @param previousNodeRef The node previous to this node
       @param nextNodeRef The node next to this node
     */
   private Node(E dataItem, Node<E> previousNodeRef, Node <E> nextNodeRef ) {
           data = dataItem;
           previous = previousNodeRef;
       next = nextNodeRef;
   }
  }
}

我的 startJosephus 方法是我认为的主要问题。虽然不完全确定。这是上面代码中的 startJosephus 方法:

/** simulates the Josephus game by killing every other person
     until the winner is the only one left.
     @return The survivor of the game
   */
 public E startJosephus() {
   E item =head.data;
   if(head.next != null){
         if(head == head.previous)
                 return item;

         else
                 while(count>1);
        removeAfter(head);
        head =head.next;
}
 return item;



 }

这是我运行 Josephus 课程时正在运行的内容:http: //pastebin.com/5GnChgYd

这是应该产生的输出:http: //pastebin.com/Qr5dCZJp

此外,以下是用于生成此输出的两个输入文件:

StudentList1.txt:http ://pastebin.com/ysjevQ8u

StudentList2.txt:http ://pastebin.com/r2YeppNm

根据我得到的输出和我应该得​​到的输出,约瑟夫斯问题似乎没有开始并模拟杀戮狂欢。但是,我不知道我的代码有什么问题。我的代码不能有尾巴,因为它是一个循环链接列表。关于我在这里做错了什么的任何想法?抱歉所有 Pastebin 链接,这似乎是组织我在这里展示的所有代码的更好方法。希望听到你的想法。

EDIT: 
There are 21 persons in this list
The game starts with McElroy,Breanna at starting position 
The killing spree begins......
The sole survivor at the end of this gruesome game is McElroy,Breanna
Exception in thread "main" java.lang.NullPointerException
at Josephus$Node.access$5(Josephus.java:383)
at Josephus.add(Josephus.java:49)
at Josephus.addLast(Josephus.java:66)
at Driver.main(Driver.java:96)

这是我在解决无限循环问题后遇到的新运行时错误。有什么建议么????所有这些空指针异常是什么

4

2 回答 2

2
if(head.next != null) {
     if (head == head.previous)
        return item;
     else
        while(count>1);
         removeAfter(head);
         head =head.next;

这段代码在所有情况下都将永远循环,除非head.next是 null 或head == head.previous,在游戏开始时总是如此。因此,除了琐碎的初始条件之外,您的程序将永远循环。显然,你打算写

if(head.next != null) {
     if (head == head.previous)
        return item;
     else
        while(count>1) {
         removeAfter(head); 
         head =head.next;
        }
于 2012-10-26T20:01:06.630 回答
1

我认为你有一个无限循环:

while (count > 1);
于 2012-10-26T20:03:28.070 回答