繁体   English   中英

循环链表帮助 (Java)

[英]Circular linked list help (Java)

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

在古老的土地上,美丽的夏娃公主有很多追求者。 她决定采用以下程序来确定她将嫁给哪个追求者。 首先,所有的求婚者将一个接一个地排成一排,并分配编号。 第一个求婚者是 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();
        }
      }
    }

我遇到的主要问题是它试图删除主方法中的每个第三个节点(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 - 更新 while 循环删除。 输出更新。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM