数据结构与算法

本文的主要内容是对《数据结构与算法分析》(Java语言描述)的学习过程记录。由于第一章和第二章主要讲解了一些数学基础和java基础,所以主要从第三章开始。

第三章 表、栈和队列

3.1 抽象类型

抽象数据类型(abstract data type ,ADT)是带有一组操作的一些对象的集合。

3.2 表ADT

这里不对太多细致的概念进行描述。主要记录一些数据结构的特点。

1. 数组

  • 特点:
    • 只有findKth操作花费常数时间。
  • 缺点:
    • 插入和删除慢,时间复杂度 O(N) 。插入和删除之后需要对影响到的所有数据进行移动。

2. 链表

  • 特点:
    • findKth 不如数组效率高,findKth(i) 花费O(i),
    • remove 方法可以通过修改一个next引用来实现。删除最后一项比较复杂,需要找出最后的节点,把它的next改为null,然后再持有最后节点的链。
    • insert 方法需要使用new操作符从系统取得一个新的节点,然后执行两次引用的调整。
    • 可以让每一个节点持有一个指向它在表中的前驱节点的链,这种链成为双链表。

3.3 Java Collections API

1. Collection接口

Collection接口扩展了Iterable接口。实现了Iterable接口的那些类可以拥有增强的for循环。

2. Iterator接口

实现Iterator接口必须提供iterator方法,该方法返回一个Iterator类型的对象。
Iterator的remove方法的优点在于,Collection的remove方法必须首先找出被删除的项。

3. List接口、ArrayList类和LinkedList

  • ArrayList
    • get() 时间消耗为常数
    • set() 时间消耗为常数
    • 缺点: add() remove() contains() 消耗昂贵,除非在末尾,前端的操作时间复杂度是 O(N)
  • LinkedList
    • addFirst()
    • removeFirst()
    • addLast()
    • removeLast()
    • 缺点:不易检索,get() 代价昂贵,contains的时间呈线性关系
  • ListIterator接口
    • 扩展了List的Iterator
    • previous()
    • hasPrevious()
    • add()
    • set()

4. ArrayList的实现


import org.omg.CORBA.Object;
import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * 第三章 3.4
 * 第47页
 * 本程序提供了一个ArrayList类的实现
 */
public class MyArrayList<AnyType> implements Iterable<AnyType> {

    public static final int DEFAULT_CAPACITY = 10;

    private int theSize;

    private AnyType[] theItems;

    public MyArrayList() {
        doClear();
    }

    public void clear() {
        doClear();
    }

    public void doClear() {
        theSize = 0;
        ensureCapacity(DEFAULT_CAPACITY);
    }

    public int size() {
        return theSize;
    }

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

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


    public AnyType get(int idx) {
        if (idx < 0 || idx > size()) {
            throw new ArrayIndexOutOfBoundsException();
        }
        return theItems[idx];
    }

    public AnyType set(int idx, AnyType anyType) {
        if (idx < 0 || idx > size()) {
            throw new ArrayIndexOutOfBoundsException();
        }
        AnyType old = theItems[idx];
        theItems[idx] = anyType;
        return old;
    }

    public void ensureCapacity(int newCapacity) {
        if (newCapacity < theSize) {
            return;
        }
        AnyType[] old = theItems;
        theItems = (AnyType[]) new Object[newCapacity];
        for (int i = 0; i < size(); i++) {
            theItems[i] = old[i];
        }
    }

    /**
     * 添加到末端的代价是昂贵的,时间复杂度O(N)
     * @param anyType
     * @return
     */
    public boolean add(AnyType anyType) {
        add(size(), anyType);
        return true;
    }

    public void add(int idx, AnyType anyType) {
        if (theItems.length == size()) {
            ensureCapacity(size() * 2 + 1);
        }
        for (int i = theSize; i < idx; i--) {
            theItems[i] = theItems[i - 1];
        }
        theItems[idx] = anyType;
        theSize++;
    }

    public AnyType remove(int idx) {
        AnyType removedItem = theItems[idx];
        for (int i = idx; i < size(); i++) {
            theItems[i] = theItems[i + 1];
        }
        theSize--;
        return removedItem;
    }

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

    public class ArrayListIterator<AnyType> implements Iterator<AnyType> {

        private int current = 0;
        private MyArrayList<AnyType> theList;

        public ArrayListIterator(MyArrayList<AnyType> list){
            theList = list;

        }

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

        /**
         * 因为next中访问theItems 是非法的,所以构造一个ArrayList<>的对象,在构造方法中将MyArrayList传递给theList
         * @return
         */
        @Override
        public AnyType next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            return theList.theItems[current ++];
        }

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

    }

}

5. LinkedList的java实现


import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * 第三章 3.5
 * 第54页
 * 本程序提供了一个LinkedList类的实现
 *
 */
public class MyLinkedList<AnyType> implements Iterable<AnyType> {

    private int theSize;
    private int modCount = 0;
    private Node<AnyType> beginMarker; // 开始标记
    private Node<AnyType> endMarker; // 结束标记

    /**
     * 节点
     * @param <AnyType>
     */
    private static class Node<AnyType>{
        public Node(AnyType d, Node<AnyType> p, Node<AnyType> n){
            data = d;
            prev = p;
            next = n;
        }

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

    public MyLinkedList() {
        doClear();
    }

    public void clear() {
        doClear();
    }

    private void doClear() {
        beginMarker = new Node<AnyType>(null, null, null);
        endMarker = new Node<AnyType>(null, beginMarker, null);
        beginMarker.next = endMarker;

        theSize = 0;
        modCount++;
    }


    public int size() {
        return theSize;
    }

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

    public void add(int idx, AnyType anyType) {
        addBefore(getNode(idx, 0, size()), anyType);
    }

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

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

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

    private AnyType remove(Node<AnyType> p) {

        p.next.prev = p.prev;
        p.prev.next = p.next;
        theSize --;
        modCount ++;
        return p.data;
    }

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

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


    @Override
    public Iterator<AnyType> iterator() {
        return new LinkedListIterator();
    }

    private class LinkedListIterator implements Iterator<AnyType> {

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

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

        @Override
        public AnyType next() {
            if(modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            if(!hasNext()) {
                throw  new NoSuchElementException();
            }

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

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


}