表、栈和队列-Java的实现

数据结构与算法分析

表、栈、队列


List接口、ArrayList类和LinkedList类

1.1 List接口继承Collection接口

public interface List<E> extends Collection<E>{
    E get(int index);
    E set(int index,E newval);
    void add(int index,E x);
    void remove(int index);
    ListIterator<E> listInterator(int pos);
    //......
}

List ADT有两种流行的实现方式

  • ArrayList 类是一种可增长数组实现。
    • 优点:对get、set 的调用花费常数时间
    • 缺点:插入项和现有项的删除代价昂贵
  • LinkedList 类提供了List ADT 的双链表实现
    • 优点:新项的插入和现有项的删除均开销很小
    • 缺点:它不容易做索引,get 的调用是昂贵的

例子
将表中所有具有偶数值的项删除

 public static void removeEvensVer(List<Integer> list) {
        Iterator<Integer> itr = list.iterator();
        while (itr.hasNext()) {
            if (itr.next() % 2 == 0) {
                itr.remove();
            }
        }
    }

如果传递一个 LinkedList<Integer> 效率高,对于一个ArrayList 即使迭代器位于需要被删除的节点上,由于其数据需要移动,其 remove()方法是昂贵的。

1.2 ListIterator 接口

ListIterator 是扩展了ListIterator的功能。

1.3 ArrayList 类的实现

public class MyArrayList<E> implements Iterable<E> {
    private static final int DEFAULT_CAPACITY = 10;
    private int size;
    private E[] items;

    public MyArrayList() {
        doClear();
    }

    private void doClear() {
        this.size = 0;
        ensureCapacity(DEFAULT_CAPACITY);
    }

    public int size() {
        return size;
    }

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

    public void trimToSize() {
        ensureCapacity(size());
    }

    public E get(int index) {
        if (index < 0 || index > size) {
            throw new ArrayIndexOutOfBoundsException();
        }
        return items[index];
    }

    public E set(int index, E newVal) {
        if (index < 0 || index > size) {
            throw new ArrayIndexOutOfBoundsException();
        }
        E old = items[index];
        items[index] = newVal;
        return old;
    }

    private void ensureCapacity(int newCapacity) {
        if (newCapacity < size) {
            return;
        }
        E[] old = items;
        items = (E[]) new Object[newCapacity];
        for (int i = 0; i < size(); i++) {
            items[i] = old[i];
        }
    }

    public boolean add(E x) {
        add(size(), x);
        return true;
    }

    public void add(int index, E x) {
        if (items.length == size()) {
            ensureCapacity(size() * 2 + 1);
        }
        for (int i = size; i > index; i--) {
            items[i] = items[i - 1];
        }
        items[index] = x;
        size++;
    }

    public E remove(int index) {
        E removeItem = items[index];
        for (int i = index; i < size() - 1; i--) {
            items[i] = items[i + 1];
        }
        size--;
        return removeItem;
    }

    @Override
    public Iterator<E> iterator() {
        return new ArrayListIterator();
    }

    private class ArrayListIterator implements Iterator<E> {

        private int current = 0;

        @Override
        public boolean hasNext() {
            return current < size();
        }

        @Override
        public E next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            return items[current++];
        }

        public void remove() {
            MyArrayList.this.remove(--current);
        }
    }
}

ensureCapacity 容量的扩充,先存储原始数组的一个引用,再为新数组分配内存,然后将旧内容拷贝到新数组中。

1.4 LinkedList 类的实现
public class MyLinkedList<E> implements Iterable<E> {

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


    private static class Node<E> {
        public Node(E d, Node<E> p, Node<E> n) {
            data = d;
            prev = p;
            next = n;
        }

        public E data;
        public Node<E> prev;
        public Node<E> next;
    }

    public MyLinkedList() {
        doClear();
    }

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

    public int size() {
        return size;
    }

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

    public boolean add(E x) {
        add(size(), x);
        return true;
    }

    public void add(int index, E x) {
        addBefore(getNode(index, 0, size()), x);
    }

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

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

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

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

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

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

    private Node<E> getNode(int index, int lower, int upper) {
        Node<E> p;
        if (index < lower || index > upper) {
            throw new IndexOutOfBoundsException();
        }
        if (index < size() / 2) {
            p = beginMarker;
            for (int i = 0; i < index; i++) {
                p = p.next;
            }
        } else {
            p = endMarker;
            for (int i = size(); i > index; i--) {
                p = p.prev;
            }
        }
        return p;
    }

    @Override
    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;// ②
        @Override
        public boolean hasNext() {
            return current != endMarker;
        }

        @Override
        public E next() {
            if (modCount != expectedModCount) {
                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;
        }
    }
}

为了检验在迭代期间集合被修改的情况,迭代器在 modCount存储在数据域expectedModCount 中,在处 如果next 已经被执行而没有其后的remove,则布尔数据域为true, OkToRemove 初始化为false ,在 next 的方法中置为true

猜你喜欢

转载自blog.csdn.net/qq_37976565/article/details/88651298