OpenDSA 全教程

Chapter 11 Design II

| 关于   «  1. 设计模式   ::   目录   ::   3. 记录比较  »

2. 线性表 ADT 的替代设计

线性表 ADT 规定,一个线性表不仅包含 按线性顺序排列的对象集合,还包含"当前位置"。 虽然这是呈现线性表所体现的主要概念的一种简单方式, 但它会使任何依赖在同一线性表中拥有两个或更多不同"当前位置"的算法 变得复杂,例如任何从两端向中间逐步推进的算法。

另一种设计是把"当前位置"分离为一个单独的对象。 在下面的 ADT 中,我们把它称为 ListIndex 。 这是一种有时被称为 迭代器 的概念的简单形式。 ListIndex 接口抽象了线性表中位置的概念。

public interface ListIndex {
  public void prev();
  public void next();
}
public interface List {
  public void clear();
  public void insert(Object it, ListIndex where);
  public void append(Object it);
  public Object remove(ListIndex where);
  public ListIndex getStart();
  public ListIndex getEnd();
  public ListIndex pointToPos(int where);
  public int length();
  public Object getValue(ListIndex where);
}

在实现中有一个问题:这两个类将如何通信。 对于基于数组的线性表, ListIndex 只需存储一个表示位置的整数。 对于链表类, ListIndex 将存储一个指向链表结点的指针。 这意味着 List 类需要能够设置和获取这个指针, 但外部任何人都不应当需要知道它。 有些语言(如 Java 和 C++)有机制允许特定类访问另一个类的非公开成员。 其他语言(如 Processing)则没有这样的概念。

一种通用的解决办法是,把 ListIndex 的接口设为公开, 但把实现作为 List 实现的一个私有内部类。 下面针对基于数组的线性表的实现就采用了这种方法。

// Array-based list implementation
class AList implements List {
  private class AListIndex implements ListIndex {
    int pos;

    AListIndex(int posit) { pos = posit; }
    public void prev() { if (pos != 0) { pos--; } }
    public void next() { if (pos < listSize) { pos++; } }
  }

  private static final int defaultSize = 10; // Default size
  private int maxSize;                    // Maximum size of list
  private int listSize;                   // Current # of list items
  private Object listArray[];             // Array holding list elements

  // Constructors
  // Create a new list object with maximum size "size"
  AList(int size) { 
    maxSize = size;
    listSize = 0;
    listArray = new Object[size];         // Create listArray
  }
  // Create a list with the default capacity
  AList() { this(defaultSize); }          // Just call the other constructor

  public void clear()                     // Reinitialize the list
    { listSize = 0; }              // Simply reinitialize values

  // Insert "it" at current position
  public void insert(Object it, ListIndex where) {
    if (listSize >= maxSize) {
      System.out.println("List capacity exceeded, nothing inserted");
      return;
    }
    int pos = ((AListIndex)where).pos;
    for (int i=listSize; i>pos; i--) {     // Shift elements up
      listArray[i] = listArray[i-1];      //   to make room
    }
    listArray[pos] = it;
    listSize++;                           // Increment list size
  }

  // Append "it" to list
  public void append(Object it) {
    if (listSize >= maxSize) {
      System.out.println("List capacity exceeded, nothing inserted");
      return;
    }
    listArray[listSize++] = it;
  }

  // Remove and return the current element
  public Object remove(ListIndex where) {
    int pos = ((AListIndex)where).pos;
    if ((pos<0) || (pos>=listSize)) {     // No current element
      return null;
    }
    Object it = listArray[pos];          // Copy the element
    for(int i=pos; i<listSize-1; i++) {    // Shift them down
      listArray[i] = listArray[i+1];
    }
    listSize--;                           // Decrement size
    return it;
  }

  // Return list size
  public int length() { return listSize; }

  // Return a ListIndex to the beginning of the list
  public ListIndex getStart() {
    return new AListIndex(0);
  }
  
  // Return a ListIndex past the end of the list
  public ListIndex getEnd() {
    return new AListIndex(listSize);
  }
  
  public ListIndex pointToPos(int pos) {
    return new AListIndex(pos);
  }

  // Return the current element
  public Object getValue(ListIndex where) {
    int pos = ((AListIndex)where).pos;
    if ((pos < 0) || (pos >= listSize)) { // No current element
      return null;
    }
    return listArray[pos];
  }
}

   «  1. 设计模式   ::   目录   ::   3. 记录比较  »

关闭窗口