【问题标题】:Circular linked list help (Java)循环链表帮助(Java)
【发布时间】:2015-04-27 01:53:53
【问题描述】:

我正在处理的程序有一些困难。我试图从一些同龄人那里获得帮助,但我们无法弄清楚。我确信它很简单,但我没有足够的经验来解决我的问题。这是作业:

在一个古老的土地上,美丽的夏娃公主有很多追求者。她决定采用以下程序来确定她将嫁给哪个追求者。首先,所有的求婚者将一个接一个地排好队,并分配号码。第一个追求者是 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 个求婚者,你应该站在哪个位置嫁给公主。您的程序应该通过删除与在流程中的每个步骤中消除的求婚者相对应的节点来模拟消除过程。

这是我目前所拥有的:

    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 方法中的每个第三个节点(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

edit 1 - 在删除中更新了 while 循环。输出已更新。

【问题讨论】:

  • 如果它是循环的,你应该检查head。如果currhead,则您已经创建了一个循环。
  • 我已经更新了 delete() 方法。我得到了不同的输出,所以有进步。

标签: java linked-list circular-list


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    这是它的要点,使用 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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-26
      相关资源
      最近更新 更多