1. 程式人生 > 實用技巧 >3.5 MyLinkedList 實現

3.5 MyLinkedList 實現

3.5 MyLinkedList 類的實現

MyLinkedList 將用雙鏈表實現,並且還需要保留該表兩端的引用。這將需要三個類

  1. MyLinkedList 類,包含到兩端的鏈、表的大小以及一些方法。
  2. Node 類 一個私有的巢狀類。一個節點包含資料以及到前一個節點的鏈和到下一個節點的鏈。
  3. LinkedListIterator 類,是一個私有類,並實現介面 Iterator。提供 next、hasNext 和 remove 的實現。

實現中會在連結串列的頭尾增加額外的標記節點,前端的頭結點和末端的尾節點。如果不使用頭結點,那麼對第 1 個結點的處理就會變成特殊情況,比如刪除時要訪問被刪除節點之前的一個節點。

public class MyLinkedList<E> implements Iterable<E> {

    private int theSize;
    private int modCount = 0;
    private Node<E> beginMarker;
    private Node<E> endMarker;

    private static class Node<E> {

        public E data;//public 訪問屬性也不會破壞封裝,因為Node在MyLinkedList中是private的
        public Node<E> prev;
        public Node<E> next;

        public Node(E data, Node<E> prev, Node<E> next) {
            this.data = data;
            this.prev = prev;
            this.next = next;
        }
    }

    private void doClear() {
        this.beginMarker = new Node<E>(null, null, null);
        this.endMarker = new Node<E>(null, beginMarker, null);
        beginMarker.next = endMarker;
        theSize = 0;
        modCount++;
    }

    public MyLinkedList() {
        doClear();
    }

    public void clear() {
        doClear();
    }

    public int size() {
        return theSize;
    }

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

    public boolean add(E e) {
        add(theSize, e);
        return true;
    }

    public void add(int idx, E e) {
        addBefore(getNode(idx, 0, theSize), e);
    }

    public E get(int idx) {
        return getNode(idx).data;
    }

    public E set(int idx, E newVal) {
        Node<E> p = getNode(idx);
        E oldVal = p.data;
        p.data = newVal;
        return oldVal;
    }

    public E remove(int idx) {
        return remove(getNode(idx));
    }

    private void addBefore(Node<E> p, E e) {
        Node<E> newNode = new Node<>(e, p.prev, p);
        newNode.prev.next = newNode;
        p.prev = newNode;
        theSize++;
        modCount++;
    }

    private E remove(Node<E> p) {
        p.next.prev = p.prev;
        p.prev.next = p.next;
        theSize--;
        modCount++;
        return p.data;
    }

    private Node<E> getNode(int idx) {
        return getNode(idx, 0, theSize - 1);
    }

    private Node<E> getNode(int idx, int lower, int upper) {
        Node<E> p;
        if (idx < lower || idx > upper) {
            throw new IndexOutOfBoundsException();
        }

        if (idx < theSize / 2) {
            p = beginMarker.next;
            for (int i = 0; i < idx; i++) {
                p = p.next;
            }
        } else {
            p = endMarker;
            for (int i = theSize; i > idx; i--) {
                p = p.prev;
            }
        }
        return p;
    }


    public Iterator<E> iterator() {
        return new LinkedListIterator();
    }

    private class LinkedListIterator implements Iterator<E>{

        private Node<E> current = beginMarker.next;
        private int expectedModCount = modCount;
        private boolean okToRemove = false;

        public boolean hasNext() {
            return current != endMarker;
        }

        public E next() {
            if (modCount != expectedModCount){//避免在使用迭代器時,被迭代器之外的方法修改了List
                throw new ConcurrentModificationException();
            }
            if(!hasNext()){
                throw new NoSuchElementException();
            }

            E nextItem = current.data;
            current = current.next;
            okToRemove = true;
            return nextItem;
        }

        public void remove(){
            if (modCount != expectedModCount){
                throw new ConcurrentModificationException();
            }
            if (!okToRemove){
                throw new IllegalStateException();
            }
            MyLinkedList.this.remove(current.prev);
            expectedModCount++;
            okToRemove = false;
        }
    }
}