【问题标题】:Trying to add a custom Node to the end of a LinkedList recursively尝试以递归方式将自定义节点添加到 LinkedList 的末尾
【发布时间】:2015-12-10 22:27:47
【问题描述】:

您好,我似乎无法将自定义节点添加到链接列表的后面。自定义节点称为ListNode,链表称为AddressList

我的程序没有崩溃或抛出任何异常,但它没有在我的AddressList 末尾添加ListNode。我的addToFront 方法有效,但我的addToBack 方法无效。我只需要有人看看我的addToBack 方法,看看我哪里出错了。

我还必须递归地执行此操作。每个ListNode 都有一些值(nametelephoneNumemailaddressdob)还有一个Next 值,它是一个ListNode,应该指向下一个ListNodeAddressList

这是我的代码:

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;
}

上面的代码部分是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;
}

以上是我的addToBack 方法。我只是不明白为什么我的程序没有抛出异常或将ListNode 添加到AddressList 的后面。任何反馈将不胜感激。

【问题讨论】:

  • 您没有在任何地方将新节点设置为下一个节点。所以节点之间没有链接。更多地关注你的空检查块
  • 什么是currentNode。在您的问题中,您没有谈论那条信息:通常链接列表仅具有对第一个节点(head)的引用。看起来好像您在类的状态中使用了 continuation-state。这可能会成为有问题的设计。

标签: java recursion linked-list


【解决方案1】:

这是有问题的代码...

  /*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(currentNode.getNext() == null)
   {
      currentNode.setNext(new ListNode(name, telephoneNum, email, address, dob));
   }

【讨论】:

  • 成功了,谢谢!!递归让我头晕目眩。
【解决方案2】:

职责分工

我认为您首先最好将一些职责分开:而不是每次都使用参数将那个用户的信息向前推进一步,而是提前构造一个节点,并将其传递给递归方法。这将稍微提高性能并使调用堆栈更小。所以像:

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

然后你需要制定一个类似的方法:

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

避免对象中的方法状态(或延续状态)

第二个问题是你AddressList 似乎有一个字段currentNode 在递归过程中被修改。这可能会带来很大的问题:它会将 continuation-state 附加到您的 AddressList。现在想象一下,稍后你想让你的类成为多线程的,那么这些线程将同时读取和操作这个字段。简而言之:这是糟糕的设计,请使用方法变量和/或参数。

所以我们要做的第一件事是获取AddressList 的头部并使用它:

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

这还不够:一个空的链表没有头head 是一个null 引用。在这种情况下,我们只需将head 设置为newNode,就完成了。所以我们将其重写为:

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

现在显然我们还需要实现核心方法:

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

实现核心方法

正如您所确定的,基本上有两种情况:current.getNext() 的基本情况是null,另一种情况不是:对于基本情况,我们只需设置@ 987654337@ 的current 到我们的newNode

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

在后一种情况下,我们前进:我们获取.getNext节点,并递归调用该方法:

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

或全部:

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);
    }
}

您可以通过防止两次调用.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);
    }
}

但这只是一个影响非常有限的细节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-25
    • 1970-01-01
    相关资源
    最近更新 更多