一、數組二三 原

數組

  • 初始容量

  • 添加元素

    • 按index添加
    • 末尾添加
    • 起始位置添加
  • 刪除元素

    • 末尾刪除
    • 索引刪除
    • 起始刪除
  • 查找

  • 包含

  • 擴容

簡單時間複雜度分析

均攤時間複雜度

複雜度震盪

代碼

package array;

/**
 * 動態數組
 * <p>
 * 思想: 新建一個新的數組,容量需要進行擴大,
 * 然後讓成員變量數組指針指向新建的數組,原來的數組
 * 沒有指針指向,會被Java 垃圾回收器回收
 * <p>
 * 時間複雜度分析:
 * 增: O(n)
 * 刪: O(n)
 * 改: 已知索引O(1),未知索引:O(n)
 * 查:已知索引O(1),未知索引:O(n)
 * <p>
 * 添加操作: 均攤時間複雜度
 * <p>
 * 複雜度震盪: capacity = n
 * addLast    擴容  之後緊接着 removeLast 兩次時間複雜度 O(n)
 * removeLast
 * 原因: removeLast 時resize() 過於着急
 * 解決方案:Lazy  縮容時候 當size == capacity/4 纔將capacity減半 空間換時間
 */
public class DynamicArray<E> {

    private E[] data;
    private int size;

    /**
     * @param capacity 傳數組的容量
     */
    public DynamicArray(int capacity) {
        data = (E[]) new Object[capacity];
        size = 0;
    }

    public DynamicArray() {
        this(10);
    }

    /**
     * @return 數組長度
     */
    public int getSize() {
        return size;
    }

    /**
     * @return 當前數組容量
     */
    public int getCapacity() {
        return data.length;
    }

    /**
     * @return 是否爲空
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 均攤時間複雜度
     * O(1)
     *
     * @param e 向所有元素後添加一個新元素
     */
    public void addLast(E e) {
        add(size, e);
    }

    /**
     * @param e 向所有元素第一個添加一個新元素 O(n)
     */
    public void addFirst(E e) {
        add(0, e);
    }

    /**
     * 指定位置添加元素
     * <p>
     * 時間複雜度,index取值的概率是一樣的
     * 每個元素期望是多少,平均時間度O(n/2) ~~ O(n),
     * 時間複雜度 :
     * 需要按照最壞的方案計算,
     * 考慮最好的意義不大
     *
     * @param index 指定位置
     * @param e     元素
     */
    public void add(int index, E e) {
        if (index < 0 || index > size) {
            throw new IllegalArgumentException("Add Failed");
        }
        if (size == data.length) {
            resize(2 * data.length);
        }
        //每一個元素向後一個位置
        for (int i = size - 1; i >= index; i--) {
            data[i + 1] = data[i];
        }
        data[index] = e;
        size++;
    }

    /**
     * 數組擴容 :
     * 思想,數組當前長度或大或小,不理想,最好是倍數
     * <p>
     * ArrayList 擴容是原來Size的1.5倍數
     * <p>
     * 時間複雜度:O(n)
     * <p>
     * 均攤時間複雜度: 假設capacity = 8, 並且每一次添加操作都是用addLast,
     * 9次addLast 操作,觸發一次resize,總共進行了17次基本操作,平均每次addLast
     * 就執行2次基本操作(擴容倍數),
     * 假設capacity = n,n+1次addLast,觸發resize,總共進行2n+1次基本操作
     * 平均每次addLast就執行2次基本操作(擴容倍數),
     *
     * @param newCapacity 新數組長度
     */
    private void resize(int newCapacity) {
        E[] newData = (E[]) new Object[newCapacity];
        for (int i = 0; i < size; i++) {
            newData[i] = data[i];
        }
        data = newData;
    }

    /**
     * 刪除一個
     *
     * @param e 刪除元素
     */
    public void removeElement(E e) {
        int index = find(e);
        if (index != -1) {
            remove(index);
        }
    }

    /**
     * 時間複雜度:O(n)
     *
     * @return
     */
    public E removeFirst() {
        return remove(0);
    }

    /**
     * 均攤時間複雜度
     * O(1)
     *
     * @return
     */
    public E removeLast() {
        return remove(size);
    }

    /**
     * 時間複雜度:O(n)
     *
     * @param index 刪除索引元素
     */
    public E remove(int index) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("Remove Failed");
        }
        E ret = data[index];
        for (int i = index + 1; i < size; i++) {
            data[i - 1] = data[i];
        }
        size--;
        data[size] = null;
        if (size == data.length / 4 && data.length / 2 != 0) {
            resize(data.length / 2);
        }
        return ret;
    }

    /**
     * 時間複雜度:O(1): 支持隨機索引
     *
     * @param index 索引
     * @param e     索引對應元素
     */
    public void set(int index, E e) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("Set Failed");
        }
        data[index] = e;
    }


    /**
     * @param index 索引
     * @return 索引對應元素
     */
    public E get(int index) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("Get Failed");
        }

        return data[index];
    }

    /**
     * 時間複雜度:O(n)
     *
     * @return 是否包含
     */
    public boolean contains(E e) {
        for (int i = 0; i < size; i++) {
            if (e.equals(data[i])) {
                return true;
            }
        }
        return false;
    }

    /**
     * 時間複雜度:O(n)
     *
     * @return 元素的索引
     */
    public int find(E e) {
        for (int i = 0; i < size; i++) {
            if (e.equals(data[i])) {
                return i;
            }
        }
        return -1;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append(String.format("Array:Size = %d , capacity = %d \n", size, data.length));
        builder.append("[");
        for (int i = 0; i < size; i++) {
            builder.append(data[i]);
            if (i != size - 1) {
                builder.append(", ");
            }
        }
        builder.append("]");
        return builder.toString();
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章