【问题标题】:Implementation of ArrayList using a LinkedList使用 LinkedList 实现 ArrayList
【发布时间】:2014-05-31 23:54:49
【问题描述】:

我需要使用内部 LinkedList 来实现 Queue 和 ArrayList。我创建了我的 DoublyLinkedList 类,并且能够毫无问题地将它实现到我的队列中。我遇到的问题是要向 ArrayList 添加或删除,添加/删除方法需要一个整数作为索引和一个对象/元素。我在 DoublyLinkedList 类中的所有方法都采用元素和/或节点。

我的问题是,当我的 DLL 类不接受任何 int 值时,如何在 ArrayList 中实现我的 DoublyLinkedList 方法。

我希望能够使用索引来添加或删除节点,但我不能。实际上,我想要像 list.addAfter(I) 这样的东西,而不需要 I 是一个整数。

注意:这个赋值的目标是实现 ADT,所以我不能修改 ArrayList ADT 的方法签名。

DoublyLinedList 类

public class DoublyLinkedList<E> {

private Node<E> head;

private Node<E> tail;

private int size;

public DoublyLinkedList() {

    this.head = new Node<E>(null, null, null);
    this.tail = new Node<E>(null, null, null);
    this.size = 0;

    head.setNext(tail);
    tail.setPrev(head);

}

public int size() {

    return size;

}

public boolean isEmpty() {

    return size == 0;
}

public Node<E> getPrev(Node<E> n) {

    return n.getPrev();

}

public Node<E> getNext(Node<E> n) {

    return n.getNext();

}

public Node<E> getFirst() {

    return head.getNext();

}

public Node<E> getLast() {

    return tail.getPrev();

}

public E remove(Node<E> c) {
    Node<E> a = c.getPrev();
    Node<E> b = c.getNext();
    b.setNext(a);
    a.setPrev(b);
    c.setNext(null);
    c.setPrev(null);
    size--;
    return c.getElement();
}

public E removeFirst() {
    return remove(head.getNext()); // first element is beyond header
}

public E removeLast() {
    return remove(tail.getPrev());
}

public void addBefore(Node<E> node, E e) {

    Node<E> prev = getPrev(node);

    Node<E> n = new Node<E>(e, prev, node);

    node.setPrev(n);
    prev.setNext(n);

    size++;

}

public void addFirst(E e) {

    addAfter(head, e);

}

public void addLast(E e) {

    addBefore(tail, e);

}

public void addAfter(Node<E> node, E e) {

    Node<E> next = getNext(node);

    Node<E> n = new Node<E>(e, node, next);
    node.setNext(n);
    next.setPrev(n);
    size++;

}

}

LArrayList 类(我的 Arraylist 实现)

public class LArrayList implements List {

private DoublyLinkedList list;

private int size;

public LArrayList() {

    this.list = new DoublyLinkedList();
    this.size = 0;

}

public int size() {
    return size;
}

public boolean isEmpty() {
    return size == 0;
}

public void add(int I, Object e) throws IndexOutOfBoundsException {

    if (isEmpty()) {

        list.addFirst(e);

    }

    // HERE IS MY CONCERN. THESE FOUR METHODS ALL TAKE IN INT VALUES WHILE
    // NON OF MY DLL METHODS DO!

}

public Object get(int i) throws IndexOutOfBoundsException {
    return null;
}

public Object remove(int i) throws IndexOutOfBoundsException {
    return null;
}

public Object set(int I, Object e) throws IndexOutOfBoundsException {
    return null;
}

}

【问题讨论】:

    标签: java arraylist linked-list internal doubly-linked-list


    【解决方案1】:

    这似乎是一件相当容易的事情 - 只需使用 LinkedList 公开的 API 并为其添加一些逻辑即可。这是您缺少的部分

    if (list.size() < I) {
        throw new IndexOutOfBoundsException()
    }
    
    //get a starting point
    Node node = list.getFirst();
    
    //loop until you get to the specified position
    while(I-- > 0) {
        node = list.getNext(node);
    } 
    
    //now node points at the node in position I - insert the new
    //node before it to comply with the List interface
    list.addBefore(node, e);
    
    this.size++;
    

    我必须注意,您的 LinkedList 实现可以改进 - 首先,getPrev() getNext() addBefore()addAfter() 应该是静态的,因为您不必使用 LinkedList 实例给他们打电话。但是,如果这些方法实际上是Node中的方法会更好,因为这样LinkedList的遍历和使用会更容易。如果方法在 Node 中,则上面的代码如下所示:

    if (list.size() < I) {
        throw new IndexOutOfBoundsException()
    }
    
    //get a starting point
    Node node = list.getFirst();
    
    //loop until you get to the specified position
    while(I-- > 0) {
        node = node.getNext();
    } 
    
    //now node points at the node in position I - insert the new
    //node before it to comply with the List interface
    node.addBefore(e);
    
    this.size++;
    

    您几乎根本不需要列表 - 当然您不需要将额外的参数传递给某些函数。您仍然可以将(希望是静态的)方法保留在链接列表中执行相同操作的方法,但它们只是方法的节点实现的代理,例如:

    public static void addAfter(Node<E> node, E e) {
        node.addAfter(e);
    }
    

    我不确定您是否需要 LinkedList 中的这些方法,但如果您愿意,它们肯定可以用于“向后合规”。

    编辑忘了提 - 第一段代码是 add() 的实现,我相信你可以解决剩下的,因为他们会做同样的事情。

    【讨论】:

    • 感谢您的帮助。我应该注意到这些方法缺少“静态”。我明白你关于在节点类中实现方法的观点。再次感谢!
    【解决方案2】:
    public Object get(int i) throws IndexOutOfBoundsException {
        if(list.size()<=i) throw new IndexOutOfBoundsException();
        Node current = list.getFirst();
        for(int x = 0; x<=i; x++){
           if(x == i) return current.getElement();//Change this behaviour for remove and set
           current = current.getNext();
        }
    }
    

    【讨论】:

    • public Object get(int i) throws IndexOutOfBoundsException { Node current = list.getFirst(); for (int x = 0; x &lt;= i; x++) { if (x != i) { current = current.getNext(); } else { return current.getElement(); } } throw new IndexOutOfBoundsException(); }
    • 以上是我的 get(i) 方法
    • 是的,很酷...所以这相当于我将return current; 更改为return current.getElement()
    • 我们也应该在循环之前抛出异常,只是为了提高性能(进行了更改)。
    猜你喜欢
    • 1970-01-01
    • 2011-11-10
    • 1970-01-01
    • 2013-08-01
    • 1970-01-01
    • 2011-08-16
    • 1970-01-01
    • 2017-10-24
    • 1970-01-01
    相关资源
    最近更新 更多