循环链表帮助(Java)

时间:2015-04-27 01:53:53

标签: java linked-list circular-list

我在处理我正在制作的计划时遇到了一些困难。我试图从一些同行那里得到帮助,但我们无法弄明白。我确定它很简单,但我没有足够的经验来解决这个问题。这是作业:

在古老的土地上,美丽的公主夏娃有许多追求者。她决定采用以下程序来确定她会嫁给哪个追求者。首先,所有的追求者将一个接一个地排队并分配号码。第一个追求者是数字1,第二个数字是2,依此类推到最后一个追求者,数字n。从第一个位置的追求者开始,她将计算三个追求者(由于她名字中的三个字母),并且第三个追求者将被取消赢得她的手并从线上移除。然后夏娃会继续,再计算三个追求者,并消除每三个追求者。当她到达终点时,她会从头开始计算。

例如,如果有六个追求者,则淘汰过程将如下进行:

123456   Initial list of suitors: start counting from 1.
12456       Suitor 3 eliminated:  continue counting from 4.
1245        Suitor 6 eliminated:  continue counting from 1.
125     Suitor 4 eliminated:  continue counting from 5.
15      Suitor 2 eliminated:  continue counting from 5.
1       Suitor 5 eliminated:  1 is the lucky winner.

编写一个程序,创建一个循环的节点链表,以确定如果有n个追求者,你应该站在哪个位置与公主结婚。您的程序应该通过删除与过程中每个步骤中消除的suitor相对应的节点来模拟消除过程。

这是我到目前为止所拥有的:

    public class CircularLinkedList
    {
      private class Node
      {
        private int candidate;
        private Node next;
        public Node()
        {
          candidate = 0;
          next = null;
        }
        public Node(int newCandidate)
        {
          candidate = newCandidate;
          next = null;
        }
        public Node(int newCandidate, Node nextValue)
        {
          candidate = newCandidate;
          next = nextValue;
        }
      }//end inner class
      private Node first;
      private Node last;
      public CircularLinkedList()
      {
        first = null;
        last = null;
      }
      public boolean isEmpty() //checks to see if the list is empty
      {
        return first == null;
      }
      public int size() //checks the size
      {
        int count = 0; 
        Node p = first;
        while(p != last)
        {
          count++;
          p = p.next;
        } 
        return count;
      }
      public void add(int e) //adds a Node to the list
      {
        Node newEntry = new Node(e, first);
        if(first==null)
        {
          last = newEntry;
          first = last;
        }
        else
        {
          last.next = newEntry;
          last = last.next;
        }
      }
      public void removeAfter(Node e) //removes the Node after the current Node
      {
        e.next = e.next.next;
      }
      public void remove() //removes every third Node 
      {
        Node curNode = first;
        int size = size();
        while(size>1)
        {
          curNode = curNode.next;
          removeAfter(curNode);
          size -= 1;
        }
      }
      public void print() //prints the list
      {
        Node ref = first;
        for(int index = -1;index<size();index++)
        {
          System.out.print(ref.candidate + " ");
          ref = ref.next;
        }
      }
    }

主要方法......

    import java.util.Scanner;
    public class CircularDemo
    {
      public static void main(String[] args)
      {
        CircularLinkedList c = new CircularLinkedList();
        System.out.println("How many candidates are there?");
        Scanner keyboard = new Scanner(System.in);
        int input = keyboard.nextInt();
        if(input<=0)
          System.out.println("No candidates presented.");
        else if(input==1)
          System.out.println("Candidate 1 is the only candidate and the winner.");
        else
        {
          for(int i = 1; i<=input; i++)
          {       
            c.add(i);
          }
          System.out.print("The candidates are: ");
          c.print();
          System.out.println("\n" + c.size()); //tests size
          while(c.size()!=1)
          {
            c.remove();
            c.print();
          }
          System.out.print("\nThe winner is: ");
          c.print();
        }
      }
    }

我遇到的主要问题是它试图删除main方法中的每个第3个节点的部分(while(c.size()!= 1))。它会在此之前正确打印所有内容。一旦达到这一点,它就像程序死了。如果我取出while循环,胜利者部分将打印出来,因此循环中的某些内容正在搞乱。

我想我知道问题出在哪里。第一个是size()方法。它比实际打印少一个。如果我放6,它认为有5个。由于这是一个循环链表,我不能让它继续计数,直到它达到空。永远不会有一个。这是一个问题,但我不确定如何解决它。

第二,我认为是在remove()和removeAfter()方法中。我试过测试它,但程序只是在尝试读取它时结束。我不确定这些程序是怎么回事,而且我有足够的时间试图弄清楚如何创建它......所以这是最大的问题。

另外还有我迄今为止得到的输出,只是为了给你一个想法:

    How many candidates are there?
    6 //user input
    The candidates are: 1 2 3 4 5 6
    5 //output for size()
    1 2 6 //output first time through while loop
    //output for winner still not showing up

编辑1 - 在删除循环时更新。输出已更新。

2 个答案:

答案 0 :(得分:2)

尝试将最后一个节点分配给第一个节点,以使其成为循环链接列表。 (在add()中分配last.next = first)

答案 1 :(得分:0)

这是要点,使用OOP方法和一些输入验证。

public class SuitorProblem
{
    public static void main(String[] args)
    {

        Scanner sc = new Scanner(System.in);
        int totalSuitors = 0;
        boolean goodInput;
        System.out.print("Enter the number of suitors: ");

        //************************************  INPUT VALIDATION  ***********************************************
        do
        {
            try
            {
                totalSuitors = sc.nextInt();
                while (totalSuitors <= 0)
                {
                    System.out.print("Enter a positive integer value greater than 0: ");
                    totalSuitors = sc.nextInt();
                }
                goodInput = true;
            }
            catch (InputMismatchException e)        //  if not integer, prompt the user to go back
            {
                System.out.print("Enter a positive integer value greater than 0: ");
                sc.nextLine();                      //  clear input
                goodInput = false;
            }
        } while (!goodInput);
        //********************************************************************************************************


        ListOfSuitors suitorList = new ListOfSuitors();
        for (int i = 1; i <= totalSuitors; i++)
            suitorList.addEnd(i);

        System.out.print("Before elimination process, the line-up of suitors is: ");
        System.out.print(suitorList.toString());
        System.out.println();

        suitorList.deleteSuitors();
        System.out.print("After  elimination process, the winning suitor is: ");
        System.out.print(suitorList.toString());
    }
}


    //  I use an extension of CircularLinkedList of type Integer, so I can have access to the methods in CircularLinkedList to manipulate the ListOfSuitors, which is a LinkedList of ints.
class ListOfSuitors extends CircularLinkedList<Integer>
{

    //  default constructor
    public ListOfSuitors()
    {
    }

    // This method is used to find the next index that needs to be deleted
    private int findIndexOfLoser(int element)
    {
        Node<Integer> current = head;
        int index = 0;
        while (current.element != element)
        {
            current = current.next;
            index++;
        }
        return index;
    }

    //  This method counts 3 spaces over then deletes a suitor by calling the delete method on the deletionIndex
    public void deleteSuitors()
    {
        Node<Integer> current = head;
        while (size != 1)
        {
            for (int i = 1; i < 3; i++)
            {
                current = current.next;
            }
            int deletionIndex = findIndexOfLoser(current.element);
            current = current.next;
            delete(deletionIndex);
        }
    }
}

    //  This is the generic circular linkedList that I extend my ListOfSuitors class from, and which holds the methods needed to manipulate the ListOfSuitors
class CircularLinkedList<E>
{

    //  since these will only be accessed by the subclass listOfSuitors, they are declared protected to increase security.
    protected Node<E> head = null;
    protected Node<E> tail = null;
    protected int size;

    public CircularLinkedList()
    {

    }

    //  method for adding a new end Node in circularLinkedList
    public void addEnd(E element)                                       //  adapted from ch24 PowerPoint
    {
        if (size == 0)
        {
            head = tail = new Node<E>(element, head);
        }
        else
        {
            tail = tail.next = new Node<E>(element, head);
        }
        size++;
    }

    //  Method for deleting a Node at a specified index in the circularLinkedList. May cause IndexOutOfBounds, so that must be handled within the method
    public void delete(int index)
    {
        if (index < 0 || index > size - 1)
            throw new IndexOutOfBoundsException("That's not a correct index.");
        else if (index == 0)
            deleteFirst();
        else if (index == size - 1)
            deleteEnd();
        else
        {
            Node<E> previous = head;
            Node<E> current = head.next;
            for (int i = 1; i < index; i++)
            {
                previous = previous.next;
                current = current.next;
            }
            previous.next = current.next;
            current.next = null;
            size--;
        }
    }

    //  method for deleting the end Node in circularLinkedList
    public void deleteEnd()
    {
        if (size == 1)
        {
            head = tail;
            tail.next = null;
        } else if (size > 1)
        {
            Node<E> current = head;
            while (current.next != tail)
                current = current.next;
            tail.next = null;
            current.next = head;
            tail = current;
        }
        size--;
    }

    //  method for deleting the first Node in circularLinkedList
    public void deleteFirst()
    {
        if (size == 1)
        {
            head = tail;
            tail.next = null;
        } else if (size > 1)
        {
            Node<E> current = head;
            head = head.next;
            current.next = null;
            tail.next = head;
        }
        size--;
    }

    //  In this method, I create my own toString in order to elegantly print the output of the suitorList in an efficient way, using StringBuilder.
    public String toString()
    {
        Node<E> current = head;
        StringBuilder suitorList = new StringBuilder();

        if (size >= 1)
        {
            suitorList.append(current.element);
            current = current.next;
        }
        for (int i = 1; i < size; i++)
        {
            suitorList.append(" ").append(current.element.toString());
            current = current.next;
        }
        return suitorList.toString();
    }
}

//  this class is for the Node, which is what each int suitor is turned into when it is added to the ListOfSuitors
class Node<E>
{

    protected E element = null;
    protected Node<E> next = null;

    //  default constructor
    public Node()
    {

    }

    //  overloaded constructor
    public Node(E element, Node<E> next)
    {
        this.element = element;
        this.next = next;
    }

    public Node(E element)
    {
        this.element = element;
    }

    public Node(Node<E> next)
    {
        this.next = next;
    }
}