基于Java的双循环链表查询

基于Java的双循环链表查询,java,data-structures,doubly-linked-list,Java,Data Structures,Doubly Linked List,下面是取自的代码,其中包含方法 next()prev()insertAfter()insertBefore()和remove() 方法需要用溶液填充 在考虑填写解决方案之前,我想问一下,如果DList类的用户将DListNodetype对象传递给上述5种方法,那么DListNode抽象数据类型是否会损坏。因为DList类如何确保该DListNode类型节点是否真的是列表的一部分 /* DList.java */ package list; /** * A DList is a mutab

下面是取自的代码,其中包含方法

next()
prev()
insertAfter()
insertBefore()
remove()

方法需要用溶液填充


在考虑填写解决方案之前,我想问一下,如果
DList
类的用户将
DListNode
type对象传递给上述5种方法,那么
DListNode
抽象数据类型是否会损坏。因为
DList
类如何确保该
DListNode
类型节点是否真的是列表的一部分

/* DList.java */

package list;

/**
 *  A DList is a mutable doubly-linked list ADT.  Its implementation is
 *  circularly-linked and employs a sentinel (dummy) node at the head
 *  of the list.
 *
 *  DO NOT CHANGE ANY METHOD PROTOTYPES IN THIS FILE.
 */

public class DList {

  /**
   *  head references the sentinel node.
   *  size is the number of items in the list.  (The sentinel node does not
   *       store an item.)
   *
   *  DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS.
   */

  protected DListNode head;
  protected int size;

  /* DList invariants:
   *  1)  head != null.
   *  2)  For any DListNode x in a DList, x.next != null.
   *  3)  For any DListNode x in a DList, x.prev != null.
   *  4)  For any DListNode x in a DList, if x.next == y, then y.prev == x.
   *  5)  For any DListNode x in a DList, if x.prev == y, then y.next == x.
   *  6)  size is the number of DListNodes, NOT COUNTING the sentinel,
   *      that can be accessed from the sentinel (head) by a sequence of
   *      "next" references.
   */

  /**
   *  newNode() calls the DListNode constructor.  Use this class to allocate
   *  new DListNodes rather than calling the DListNode constructor directly.
   *  That way, only this method needs to be overridden if a subclass of DList
   *  wants to use a different kind of node.
   *  @param item the item to store in the node.
   *  @param prev the node previous to this node.
   *  @param next the node following this node.
   */
  protected DListNode newNode(Object item, DListNode prev, DListNode next) {
    return new DListNode(item, prev, next);
  }

  /**
   *  DList() constructor for an empty DList.
   */
  public DList() {
    this.head = new DListNode(Integer.MIN_VALUE, null, null);
    this.head.next = this.head;
    this.head.prev = this.head;
    this.size = 0;
  }


  /**
   *  next() returns the node following "node" in this DList.  If "node" is
   *  null, or "node" is the last node in this DList, return null.
   *
   *  Do NOT return the sentinel under any circumstances!
   *
   *  @param node the node whose successor is sought.
   *  @return the node following "node".
   *  Performance:  runs in O(1) time.
   */
  public DListNode next(DListNode node) {
    if(node.next != this.head){
        return node.next; 
    }else{
        return null;
    }
  }

  /**
   *  prev() returns the node prior to "node" in this DList.  If "node" is
   *  null, or "node" is the first node in this DList, return null.
   *
   *  Do NOT return the sentinel under any circumstances!
   *
   *  @param node the node whose predecessor is sought.
   *  @return the node prior to "node".
   *  Performance:  runs in O(1) time.
   */
  public DListNode prev(DListNode node) {
    if(node.prev != this.head){
        return node.prev;
    }else{
        return null;
    }
  }

  /**
   *  insertAfter() inserts an item in this DList immediately following "node".
   *  If "node" is null, do nothing.
   *  @param item the item to be inserted.
   *  @param node the node to insert the item after.
   *  Performance:  runs in O(1) time.
   */
  public void insertAfter(Object item, DListNode node) {
    //Your solution here
      /*if(node != null){
        node.next = new DListNode(item, node, node.next);
        node.next.next.prev = node.next;
    }*/
  }

  /**
   *  insertBefore() inserts an item in this DList immediately before "node".
   *  If "node" is null, do nothing.
   *  @param item the item to be inserted.
   *  @param node the node to insert the item before.
   *  Performance:  runs in O(1) time.
   */
  public void insertBefore(Object item, DListNode node) {
    // Your solution here.
  }

  /**
   *  remove() removes "node" from this DList.  If "node" is null, do nothing.
   *  Performance:  runs in O(1) time.
   */
  public void remove(DListNode node) {
    // Your solution here.
  }

  /**
   *  toString() returns a String representation of this DList.
   *
   *  DO NOT CHANGE THIS METHOD.
   *
   *  @return a String representation of this DList.
   *  Performance:  runs in O(n) time, where n is the length of the list.
   */
  public String toString() {
    String result = "[  ";
    DListNode current = head.next;
    while (current != head) {
      result = result + current.item + "  ";
      current = current.next;
    }
    return result + "]";
  }
}

我的问题:


DList
类如何确保传递给上述方法的
DListNode
类型节点是否为真节点?通过传递节点,我们是否有机会打破前面提到的
DList
ADT的不变量?

DList
的用户可以只传递项而不是传递节点,但用户需要访问节点以避免N^2算法在他身边。因此,用户可以操作
,但不能操作
上一个
下一个
引用。当用户使用这5种方法之一时,比较整个列表中传递的节点以检查真正的节点也没有意义。因为这是一个代价高昂的操作,所以代码的“安全”或“不安全”与您所做的完全相同。它可以写得完全偏执,完全未经检查,或者可以包含一些基本检查以捕获大多数使用错误。这取决于你。我没有得到你的答案。你们的意思是,若不进行检查,那个么列表就有可能被破坏。如果检查完成,那么这5项操作将是一件昂贵的事情?代价有多大取决于您,取决于您的聪明才智。
/* DListNode.java */

package list;

/**
 *  A DListNode is a node in a DList (doubly-linked list).
 */

public class DListNode {

  /**
   *  item references the item stored in the current node.
   *  prev references the previous node in the DList.
   *  next references the next node in the DList.
   *
   *  DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS.
   */

   public Object item;
   protected DListNode prev;
   protected DListNode next;


  /**
   *  DListNode() constructor.
   *  @param i the item to store in the node.
   *  @param p the node previous to this node.
   *  @param n the node following this node.
   */
  DListNode(Object i, DListNode p, DListNode n) {
    this.item = i;
    this.prev = p;
    this.next = n;
  }
}