簡體   English   中英

Java鏈表序列insertFirst方法將對象插入兩次

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

我正在嘗試用Java實現鏈接列表序列,但是我在序列開頭插入對象的方法將對象插入兩次,但我不明白為什么。

如果有人可以提供幫助,我們將不勝感激。

我的測試程序的當前輸出是

30 30

但我希望是30歲

提前致謝

下面是序列的代碼和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);
    }       
}
}

這是我的測試程序

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

這是經過測試的最終版本,可以完美運行! 希望這可以幫助:

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

假設您正在嘗試創建一個單鏈表,那么您將得到以下結果:

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

執行該操作時,您listHead新節點分配給listHeadlistTail 你應該有

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

看起來它只被添加了一次,但是被打印了兩次。

如果展開循環:

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

您基本上得到:

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

因此,如果這是意外行為,那么我們真正需要診斷的是element()方法。

當調用s.element(2)並且“ s”僅包含一個元素時,您想發生什么? 是否應該將索引超出范圍異常? 當索引超出列表范圍時(應該是當前行為),它應該環繞或裁剪到范圍內嗎?

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