简体   繁体   English

Java链表序列insertFirst方法将对象插入两次

[英]Java Linked List Sequence insertFirst method inserts object twice

I am trying to implement a Linked List Sequence in Java however my method for inserting an object at the start of the sequence inserts the object twice and I don't understand why. 我正在尝试用Java实现链接列表序列,但是我在序列开头插入对象的方法将对象插入两次,但我不明白为什么。

If anyone can help it would be really appreciated. 如果有人可以提供帮助,我们将不胜感激。

The current output of my test program is 我的测试程序的当前输出是

30 30 30 30

but I want it to be 30 但我希望是30岁

Thanks in advance 提前致谢

Below is the code for the sequence and the method for insertFirst 下面是序列的代码和insertFirst的方法

public class Sequence implements SequenceInterface{

private Node listHead; 
private Node listTail; 

protected class Node{

      protected Object datum; 
      protected Node next; 

      public Node(Object o, Node n) { 
           datum = o; 
           next = n; 
      }

}


//Constructor 
public Sequence(){ 
   listHead = null; 
   listTail = null;
}


public void insertFirst(Object o) {

    if(listHead == null){

         listHead = new Node(o, listTail); 
         listTail = listHead; 

    }else{
        Node oldLH = listHead;
        listHead = new Node(o, oldLH);
    }       
}
}

Here is my test program 这是我的测试程序

public class SequenceTest {
/**
 * @param args
 * @throws Exception 
 */
public static void main(String[] args) throws Exception {
    Sequence s = new Sequence();    
    s.insertFirst(new Integer(30));

    for(int i=0; i<2; i++){
        System.out.println(s.element(i));
    }
}
}

This is the final version tested that works perfectly! 这是经过测试的最终版本,可以完美运行! Hope this helps: 希望这可以帮助:

class SequenceDLListException extends Exception {
  SequenceDLListException() {
    super();
  }
  SequenceDLListException(String s) {
    super(s);
  }
}

/**
 * <dl>
 * <dt>Purpose: Implementation of Sequence ADT.
 * <dd>
 *
 * <dt>Description:
 * <dd>This class is an implementation of the Sequence using an linked list as
 * the underlying data structure. The capacity is therefore unlimited and
 * overflow does not need to be checked.
 * </dl>
 *
 *
 * @version $Date: 2015/01/30
 */

public class SequenceDLList {
  /**
   * Member class Node encapsulates the nodes of the linked list in
   * which the stack is stored. Each node contains a data item and a
   * reference to another node - the next in the linked list.
   * 
   * 
   */


  public Node lastNode() {
            return listTail;
        }

  public Node firstNode() {
            return listHead;
        }
  protected class Node {

    public Node(Object o) {
      this(o, null, null);
    }

      /**
      * I added another null because it has to point at the beginning and at the end 
      * to some kind of terminator to facilitate the traversal of the list
      */

    public Node(Object o, Node p, Node n) {
      datum = o;
      prev =p;
      next = n;
    }
      /**
      * I added another Node because every node has two links now with the Doubly Linked List
      */



    //The Node data structure consists of two object references.
    //One for the datum contained in the node and the other for
    //the next node in the list.

    protected Object datum;
    protected Node next;
    protected Node prev;
  }

  //We use object references to the head and tail of the list (the head
  //and tail of the sequence, respectively).
  private Node listHead;
  private Node listTail;

  //Only require a single constructor, which sets both object
  //references to null.
  /**
   * Constructs an empty sequence object.
   */
  public SequenceDLList() {
    listHead = null;
    listTail = null;
  }

  /**
   * Adds a new item at the start of the sequence.
   */
  public void insertFirst(Object o) {
    //There is a special case when the sequence is empty.
    //Then the both the head and tail pointers needs to be
    //initialized to reference the new node.
    if (listHead == null) {
      listHead = new Node(o, listHead, null);
      listTail = listHead;
    }

    //In the general case, we simply add a new node at the start
    //of the list via the head pointer.
    else {
      listHead = new Node(o, listHead, null);
    }
  }

  /**
   * Adds a new item at the end of the sequence.
   */
  public void insertLast(Object o) {
    //There is a special case when the sequence is empty.
    //Then the both the head and tail pointers needs to be
    //initialized to reference the new node.
    if (listHead == null) {
      listHead = new Node(o, listHead, null);
      listTail = listHead;
    }

    //In the general case, we simply add a new node to the end
    //of the list via the tail pointer.
    else {
      listTail.next = new Node(o, listTail, null);
      listTail = listTail.next;
    }
  }

  /**
   * Adds a new item at a specified position in the sequence.
   */
  public void insert(Object o, int index) throws SequenceDLListException {
    //Check the index is positive.
    if (index < 0) {
      throw new SequenceDLListException("Indexed Element out of Range");
    }

    //There is a special case when the sequence is empty.
    //Then the both the head and tail pointers needs to be
    //initialized to reference the new node.
    if (listHead == null) {
      if (index == 0) {
        listHead = new Node(o, listHead, null);
        listTail = listHead;
      } else {
        throw new SequenceDLListException("Indexed element is out of range");
      }
    }

    //There is another special case for insertion at the head of
    //the sequence.
    else if (index == 0) {
      listHead = new Node(o, listHead, null);
    }

    //In the general case, we need to chain down the linked list
    //from the head until we find the location for the new
    //list node. If we reach the end of the list before finding
    //the specified location, we know that the given index was out
    //of range and throw an exception.
    else {
      Node nodePointer = listHead;
      int i = 1;
      while (i < index) {
        nodePointer = nodePointer.next;
        i += 1;
        if (nodePointer == null) {
          throw new SequenceDLListException("Indexed Element out of Range");
        }
      }
       Node newNode = new Node(o, nodePointer, nodePointer.next);
        if (nodePointer.next != null) {
            nodePointer.next.prev = newNode;
        }
      //Now we've found the node before the position of the
      //new one, so we 'hook in' the new Node.

      nodePointer.next = newNode;

      //Finally we need to check that the tail pointer is
      //correct. Another special case occurs if the new
      //node was inserted at the end, in which case, we need
      //to update the tail pointer.
      if (nodePointer == listTail) {
        listTail = newNode;
      }
    }
  }

  /**
   * Removes the item at the start of the sequence.
   */
  public void deleteFirst() throws SequenceDLListException {
    //Check there is something in the sequence to delete.
    if (listHead == null) {
      throw new SequenceDLListException("Sequence Underflow");
    }

    //There is a special case when there is just one item in the
    //sequence. Both pointers then need to be reset to null.
    if (listHead.next == null) {
      listHead = null;
      listTail = null;
    }

    //In the general case, we just unlink the first node of the
    //list.
    else {
      listHead = listHead.next;
      listHead.prev = null;
    }
  }

  /**
   * Removes the item at the end of the sequence.
   */
  public void deleteLast() throws SequenceDLListException {
    //Check there is something in the sequence to delete.
    if (listHead == null) {
      throw new SequenceDLListException("Sequence Underflow");
    }

    //There is a special case when there is just one item in the
    //sequence. Both pointers then need to be reset to null.
    if (listHead.next == null) {
      listHead = null;
      listTail = null;
    }

    //In the general case, we need to chain all the way down the
    //list in order to reset the link of the second to last
    //element to null.
    else {
      Node nodePointer = listHead;
      while (nodePointer.next != listTail) {
        nodePointer = nodePointer.next;
      }

      //Unlink the last node and reset the tail pointer.
      nodePointer.next = null;
      listTail = nodePointer;
    }
  }

  /**
   * Removes the item at the specified position in the sequence.
   */
  public void delete(int index) throws SequenceDLListException {
    //Check there is something in the sequence to delete.
    if (listHead == null) {
      throw new SequenceDLListException("Sequence Underflow");
    }

    //Check the index is positive.
    if (index < 0) {
      throw new SequenceDLListException("Indexed Element out of Range");
    }

    //There is a special case when there is just one item in the
    //sequence. Both pointers then need to be reset to null.
    if (listHead.next == null) {
      if (index == 0) {
        listHead = null;
        listTail = null;
      } else {
        throw new SequenceDLListException("Indexed element is out of range.");
      }
    }

    //There is also a special case when the first element has to
    //be removed.

    else if (index == 0) {
      deleteFirst();
    }

    //In the general case, we need to chain down the list to find
    //the node in the indexed position.
    else {
      Node nodePointer = listHead;
      int i = 1;
      while (i < index) {
        nodePointer = nodePointer.next;
        i += 1;
        if (nodePointer.next == null) {
          throw new SequenceDLListException("Indexed Element out of Range");
        }

      }

      //Unlink the node and reset the tail pointer if that
      //node was the last one.
      if (nodePointer.next == listTail) {
        listTail = nodePointer;
      }

      //When we remove the node we have to change the reference as well!
        if (nodePointer.next.next != null) {
            nodePointer.next.next.prev = nodePointer;
        }
      nodePointer.next = nodePointer.next.next;
    }
  }

  /**
   * Returns the item at the start of the sequence.
   */
  public Object first() throws SequenceDLListException {
    if (listHead != null) {
      return listHead.datum;
    } else {
      throw new SequenceDLListException("Indexed Element out of Range");
    }
  }

  /**
   * Returns the item at the end of the sequence.
   */
  public Object last() throws SequenceDLListException {
    if (listTail != null) {
      return listTail.datum;
    } else {
      throw new SequenceDLListException("Indexed Element out of Range");
    }
  }

  /**
   * Returns the item at the specified position in the sequence.
   */
  public Object element(int index) throws SequenceDLListException {
    //Check the index is positive.
    if (index < 0) {
      throw new SequenceDLListException("Indexed Element out of Range");
    }

    //We need to chain down the list until we reach the indexed
    //position

    Node nodePointer = listHead;
    int i = 0;
    while (i < index) {
      if (nodePointer.next == null) {
        throw new SequenceDLListException("Indexed Element out of Range");
      } else {
        nodePointer = nodePointer.next;
        i += 1;
      }
    }

    return nodePointer.datum;
  }

  /**
   * Tests whether there are any items in the sequence.
   */
  public boolean empty() {
    return (listHead == null);
  }

  /**
   * Returns the number of items in the sequence.
   */
  public int size() {
    //Chain down the list counting the elements

    Node nodePointer = listHead;
    int size = 0;
    while (nodePointer != null) {
      size += 1;
      nodePointer = nodePointer.next;
    }
    return size;
  }

  /**
   * Empties the sequence.
   */
  public void clear() {
    listHead = null;
    listTail = null;
  }
}

Assuming you are trying to create a singly linked list, you've got this backwards: 假设您正在尝试创建一个单链表,那么您将得到以下结果:

     listHead = new Node(o, listTail); 
     listTail = listHead;

When you execute that, you are assigning the new node to both listHead and listTail . 执行该操作时,您listHead新节点分配给listHeadlistTail You should have 你应该有

     listTail = listHead;
     listHead = new Node(o, listTail); 

It looks like it is only added once, but is being printed twice. 看起来它只被添加了一次,但是被打印了两次。

If you unroll the loop: 如果展开循环:

for(int i=0; i<2; i++){
    System.out.println(s.element(i));
}

you essentially get: 您基本上得到:

System.out.println(s.element(0));
System.out.println(s.element(1));

so if this is unexpected behaviour, what we really need to look at to diagnose it is the element() method. 因此,如果这是意外行为,那么我们真正需要诊断的是element()方法。

What do you want to happen when s.element(2) is called and 's' only contains one element? 当调用s.element(2)并且“ s”仅包含一个元素时,您想发生什么? Should it throw an index out of range exception? 是否应该将索引超出范围异常? Should it wrap or crop to within range when it is indexed past the lists range (presumably the current behaviour)? 当索引超出列表范围时(应该是当前行为),它应该环绕或裁剪到范围内吗?

public void insertFirst(Object o) {

    Node newNode = new Node(o, listHead);
    if (listHead == null) {
        listHead = newNode; 
        listTail = listHead;
    } else {
        listHead = newNode; 
    }       
}

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

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