使用尾递归的双链表

时间:2016-12-02 14:58:47

标签: java algorithm data-structures tail-recursion doubly-linked-list

我正在努力使我的双向链表使用尾递归。

public class DoublyLinkedList
{
    private int noOfItems;
    private DLLNode head;
    private DLLNode tail;
  // Default constructor
  public DoublyLinkedList()
  {
     head = null;
     tail = null;
     this.noOfItems = 0;

  }

public void AddItem(String value)
{
   DLLNode newNode = new DLLNode(value);

   if (head == null)
   {
       head = newNode;
       noOfItems++;
   }
   else {
       DLLNode current = head;

       while(current != null) {
           if (current.GetNextNode() == null) {
               current.setNextNode(newNode);

               newNode.setPrevious(newNode);
               noOfItems++;
               break;
           }
           current = current.GetNextNode();

           }
       }

   }
}

我的Node类如下:

public class DLLNode
{
    private DLLNode previous;
    public DLLNode next;
    private String value;

    public DLLNode(String value)
    {
        this.value = value;
    }
  /* This method returns the String item of data held in this node */
  public String GetDataItem()
  {
    return value;
  }

  public void setDataItem()
  {
      this.value = value;
  }

  /* This method returns the node immediately prior to this node in the list or
   * null if there is no such node */
  public DLLNode GetPreviousNode()
  {
    return previous;
  }

  public void setPrevious(DLLNode previous)
  {
      this.previous = previous;
  }

  /* This method returns the node immediately after this node in the list or null
   * if there is no such node. */
  public DLLNode GetNextNode()
  {
    return next;
  }

  public void setNextNode(DLLNode next)
  {
      this.next = next;
  }

   public void AddItem(String value)
    {
       if (next == null)
       {
           next = new DLLNode(value);
       }
       else
           next.AddItem(value);
    }



}

这是我添加项目的代码。我还尝试使用尾递归,这是下面显示的代码:

 public void AddItem(String value)
  {
       if (head == null)
       {
           head = new DLLNode(value);
           noOfItems++;
       }
       else {

          head.AddItem(value);
       }

 }

我写的递归版本有效。然而,它并没有双重联系。

我理解,要成为一个双向链表,节点需要知道接下来会发生什么以及接下来会发生什么。所以在我的Add Item中,我需要一些东西让下一个节点知道它之前发生了什么吗?如果有任何关于如何做的建议?

先谢谢。

1 个答案:

答案 0 :(得分:1)

使用我自己的假设Node课程 - 您可以根据自己的DLLNode进行调整:

void addItem(Node head, Node item) {
     if(node.next == null) {
          // Stopping condition
          node.next = item;
          item.previous = node;
     } else {
          // Recurse
          addItem(node.next, item);
     }
}

或者,多一点OO,假设此代码是Node的一部分,只需将head替换为this,您需要更少的方法参数:

void addItem(Node item) {
     if(this.next == null) {
          // Stopping condition
          this.next = item;
          item.previous = this;
     } else {
          // Recurse
          this.next.addItem(item);
     }
}

或者,如果您不想传递Node,而是创建一个:

public void addItem(String value) {
     if(this.next == null) {
          // Stopping condition
          Node newNode = new Node(value, this, null);
          this.next = newNode;
     } else {
          // Recurse
          this.next.addItem(value);
     }
}

这假设一个构造函数:

public Node(String value, Node previous, Node next) {
     this.value = value;
     this.previous = previous;
     this.next = next;
}

我认为这显示了整洁的基础知识。您可以使用getter / setter等来改进它。

我已经为你提供了Node的方法,但是你有一个包含它的DoublyLinkedList类。对于列表类来说,在节点上的方法是一个非常薄的包装器是很常见的:

 public class DoublyLinkedList {
       private Node head;

       public addItem(String value) {
            head.addItem(value);
       }
 }

(你需要处理head为空的情况。为了简洁,我把它留了出来)

请注意,在Java中,这种递归解决方案并不理想,因为该语言不会优化尾递归,而对于长列表,您将获得堆栈溢出。迭代解决方案不会消耗堆栈。