简体   繁体   中英

Implementation of ArrayList using a LinkedList

I need to implement both a Queue and ArrayList by using an internal LinkedList. I created my DoublyLinkedList class and was able to implement it into my queue with no problem. The problem I am running into is that to add or delete to/from the ArrayList, the add/delete methods take in a integer for the index and an object/element. All my methods inside my DoublyLinkedList class take in either elements and/or Nodes.

My question is this, how can I implement my DoublyLinkedList methods inside my ArrayList when my DLL class doesn't take any int values in.

I want to be able to add or delete the node by using the index, but I can't. Realistically, I would want something like list.addAfter(I) without I being an integer.

Note: The goal of this assignment is to implement ADTs, so I can't modify the method signatures of the ArrayList ADT.

DoublyLinedList Class

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 class (my Arraylist implementation)

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

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

It seems like a fairly easy thing to do - just use the API exposed by your LinkedList and add some logic to it. Here is the bit you are missing

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

I do have to note that your LinkedList implementation can be improved - first of all, the getPrev() getNext() addBefore() and addAfter() should be static, as you shouldn't have to use a LinkedList instance to call them. However, it would be even better if the methods were actually methods in Node, because that way the traversal and usage of the LinkedList would be way more easy. Here is how the above code would look like if the methods were in 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++;

You pretty much do not need the list at all - certainly you don't need to just pass extra parameters to some functions. You can still keep the (hopefully static) methods in Linked list that do the same thing, but they'd just be proxies for the Node implementation of the methods, eg:

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

I am not sure if you will need these methods in LinkedList but they can certainly be there for "backwards compliance", if you will.

EDIT Forgot to mention - the fist bit of code is the implementation for add(), I am sure you can work out the rest, as they'd do the same thing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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