简体   繁体   English

尝试以递归方式将自定义节点添加到LinkedList的末尾

[英]Trying to add a custom Node to the end of a LinkedList recursively

Hi I seem to having trouble adding custom nodes to the back of my l inked list. 嗨,我似乎很难在自定义列表的后面添加自定义节点。 The custom node is called ListNode and the linked list is called AddressList . 自定义节点称为ListNode ,而链接列表称为AddressList

My program does not crash or throw any exceptions but it does not add a ListNode to the end of my AddressList . 我的程序不会崩溃或引发任何异常,但不会将ListNode添加到我的AddressList的末尾。 My addToFront method works but not my addToBack method. 我的addToFront方法有效,但我的addToBack方法addToBack I just need someone to look at my addToBack method and see where I am going wrong. 我只需要有人看看我的addToBack方法,看看我哪里出了问题。

I also have to do this recursively. 我还必须递归执行此操作。 Each ListNode has some values ( name , telephoneNum , email , address , dob ) and also a Next value which is a ListNode that should point to the next ListNode in the AddressList . 每个ListNode具有一定的值( nametelephoneNumemailaddressdob ),也是一个Next值,它是一个ListNode应该指向下一ListNodeAddressList

This is my code: 这是我的代码:

public ListNode(String name, String telephoneNum, String email, String address, String dob) {
    this.name = name;
    this.telephoneNum = telephoneNum;
    this.email = email;
    this.address = address;
    this.dob = dob;
}

public ListNode getNext() {
   return next;
}

public void setNext(ListNode link) {
   next = link;
}

The code section above is the constructor for the ListNode and the methods to get and set the next link in the AddressList . 上面的代码部分是ListNode的构造函数,以及用于获取和设置AddressList的下一个链接的方法。

public void addToBack(String name, String telephoneNum, String email, String address, String dob) {
    /*Base case.*/
    /*If the next node in the AddressList is null add the ListNode to that node.*/
    if(currentNode.getNext() == null) {
        currentNode = currentNode.getNext();
        currentNode = new ListNode(name, telephoneNum, email, address, dob);
    }
    /*Recursive case.*/
    /*If the AddressList still has nodes after the currentNode, keep going.*/
    else {
        currentNode = currentNode.getNext();
        addToBack(name, telephoneNum, email, address, dob);
    }
    currentNode = head;
}

Above is my addToBack method. 上面是我的addToBack方法。 I just don't understand why my program isn't throwing an exception or adding the ListNode to the back of the AddressList . 我只是不明白为什么我的程序不会引发异常或将ListNode添加到AddressList的后面。 Any feedback will be appreciated. 任何反馈将不胜感激。

Here is the offending piece of code... 这是令人讨厌的代码...

  /*Base case.*/
   /*If the next node in the AddressList is null add the ListNode to that node.*/
   if(currentNode.getNext() == null)
   {
      currentNode = currentNode.getNext();
      currentNode = new ListNode(name, telephoneNum, email, address, dob);
   }

If you reach the null case you need to set the next node as a new node ... I propose something like this 如果达到空值情况,则需要将下一个节点设置为新节点。

   if(currentNode.getNext() == null)
   {
      currentNode.setNext(new ListNode(name, telephoneNum, email, address, dob));
   }

Separate responsibilities 分开的责任

I think you first better separate some responsibilities: instead of each time using arguments to advance the information of that user one step further, construct a node in advance, and pass this to the recursive method. 我认为您首先最好将一些职责分开:不要每次都使用参数来进一步推进该用户的信息,而是先构造一个节点,然后将其传递给递归方法。 This will boost performance a bit and make the call stack smaller. 这将提高性能,并使调用堆栈更小。 So something like: 所以像这样:

public void addToBack(String name, String telephoneNum, String email, String address, String dob) {
    addToBack(new ListNode(name,telephoneNum,email,address,dob));
}

And then you need to work out a method like: 然后,您需要制定一种方法,例如:

public void addToBack(ListNode newNode) {
    //TODO: implement
    //...
}

Avoid method state (or continuation state) in objects 避免对象中的方法状态(或延续状态)

A second problem is that you're AddressList seems to have a field currentNode that is modified in the recursive process. 第二个问题是您的AddressList似乎有一个currentNode字段,该字段在递归过程中被修改。 This can be very problematic: it attaches a continuation-state to your AddressList . 这可能会造成很大的问题:它将延续状态附加到您的AddressList Now imagine that later you want to make your class multi-threaded, then these threads will concurrently read and manipulate this field. 现在想象一下,稍后您想使您的类成为多线程,那么这些线程将同时读取和操作该字段。 In short: it is bad design, use a method variable and/or parameter. 简而言之:这是糟糕的设计,请使用方法变量和/或参数。

So the first thing we do is fetch the head of the AddressList and use that: 因此,我们要做的第一件事是获取AddressList的头并使用它:

public void addToBack(ListNode newNode) {
    this.addToBack(this.head,newNode);
}

This is not sufficient: an empty linked list has no head : head is a null reference. 这还不够:空的链表没有headheadnull引用。 In that case we simply set the head to the newNode and we're done. 在这种情况下,我们只需将head设置为newNode so we rewrite this to: 因此我们将其重写为:

public void addToBack(ListNode newNode) {
    if(this.head == null) {
        this.head = newNode;
    } else {
        this.addToBack(this.head,newNode);
    }
}

Now evidently we still need to implement the core method: 现在显然我们仍然需要实现核心方法:

public void addToBack(ListNode current, ListNode newNode) {
    //TODO: implement
    //...
}

Implement the core-method 实施核心方法

As you identified yourself, there are basically two cases: the base case in which the .getNext() of current is null , an the one where it is not: for the base case, we simply set the .setNext of current to our newNode : 当你确定你自己,基本上有两种情况:基本情况,其中.getNext()currentnull ,一个一个地方是不是:基础方案,我们简单地设置.setNextcurrent我们的newNode

if(current.getNext() == null) {
    current.setNext(newNode);
}

In the latter case, we advance: we fetch the .getNext node, and call the method recursively: 在后一种情况下,我们前进:获取.getNext节点,然后递归调用该方法:

else {
    addToBack(current.getNext(),newNode);
}

Or all together: 或一起:

public void addToBack(String name, String telephoneNum, String email, String address, String dob) {
    //separate responsibilities, by constructing the node first
    addToBack(new ListNode(name,telephoneNum,email,address,dob));
}

public void addToBack(ListNode newNode) {
    //do not use a continuation state in a class, fetch the head, inspect the head and if not null pass to the recursion method
    if(this.head == null) {
        this.head = newNode;
    } else {
        this.addToBack(this.head,newNode);
    }
}

public void addToBack(ListNode current, ListNode newNode) {
    //generic method that adds the node at the end
    if(current.getNext() == null) {//base case: current is the last node
        current.setNext(newNode);
    } else {//recursive case, current is not the next node
        addToBack(current.getNext(),newNode);
    }
}

You can make the last method a bit faster by preventing to call the .getNext method twice: 通过防止两次调用.getNext方法,可以使最后一个方法快一些:

public void addToBack(ListNode current, ListNode newNode) {
    //generic method that adds the node at the end
    ListNode nx = current.getNext();
    if(nx == null) {//base case: current is the last node
        current.setNext(newNode);
    } else {//recursive case, current is not the next node
        addToBack(nx,newNode);
    }
}

but that's just a detail that will have very limited impact. 但这只是一个细节,影响将非常有限。

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

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