数据结构与算法分析
表、栈、队列
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
是扩展了List
的 Iterator
的功能。
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