【數據結構】數組

什麼是數組?

數組對應的英文是array,是一個存儲相同類型的變量所組成的一個有序集合,數組中每個變量稱爲元素,每一個元素都有一個對應的索引(索引從0開始)。
數組的存儲方式以下:
數組.png
數組還有另外一個特色,就是在內存中是順序存儲的。
內存是由一個個連續的內存單元所組成的,每個內存單元都對應一個地址,在內存單元中,有些被佔用了,有些是空閒的。
數組中的每個元素,都存儲在內存單元中,而且這些內存單元之間緊密排列,既不能打亂存儲順序,也不能跳過某個內存單元進行存儲。數組

基於數組進行二次封裝

一、讀取元素
對於數組來講,讀取元素是最簡單的操做。因爲數組在內存中順序存儲,因此只要給出一個數組的索引,就能夠讀取到索引對應的元素。app

二、修改元素
更新數組中的某一個元素,也是一個很是簡單的操做。直接利用數組的索引,就能夠把新值賦值給索引對應的元素。ide

三、插入元素
在數組中插入元素分爲三種狀況:函數

  • 尾部插入

    這是最簡單的狀況,直接把插入的元素放在數組的尾部空閒的位置就能夠了。ui

  • 中間插入

    稍微複雜一些,在數組中每個元素都對應一個索引,因此首先先把插入位置的元素和後面的元素向後移動,再把插入的元素插入到對應的索引中。this

  • 超範圍插入

    假如如今有一個長度爲10的數組,而且這個數組中已經填滿了元素,若是這時還想添加一個元素,該怎麼辦?
    這裏就涉及到了擴容機制了,在一開始數組的長度就已經肯定了,那麼如何擴容呢?
    咱們能夠建立一個新的數組,而且這個新數組的長度是原來的數組的長度的2倍,而後再把舊數組當中的元素插入到新數組當中,這樣就實現了數組的擴容。code

四、刪除元素
刪除元素和插入元素的過程正好相反,咱們把要刪除的元素後面的元素往前移動就能夠了。注意:雖然這裏不涉及擴容問題,可是若是當前的數組的元素的個數要比數組的長度小不少,是否是就浪費了內存?因此咱們能夠在這裏加入縮容機制,防止浪費內存。orm

總體代碼以下:blog

/**
 * 描述:基於數組二次封裝成動態數組。
 * <p>
 * Create By ZhangBiao
 * 2020/5/8
 */
public class Array<E> {

    private E[] data;

    private int size;

    /**
     * 構造函數,傳入數組的容量capacity構造Array。
     *
     * @param capacity 容量大小
     */
    public Array(int capacity) {
        data = (E[]) new Object[capacity];
        size = 0;
    }

    /**
     * 無參數的構造函數,默認數組的容量capacity=10。
     */
    public Array() {
        this(10);
    }

    public Array(E[] arr) {
        this.data = (E[]) new Object[arr.length];
        for (int i = 0; i < arr.length; i++) {
            this.data[i] = arr[i];
        }
        this.size = this.data.length;
    }

    /**
     * 獲取數組的容量。
     *
     * @return
     */
    public int getCapacity() {
        return data.length;
    }

    /**
     * 獲取數組中的元素個數。
     *
     * @return
     */
    public int getSize() {
        return size;
    }

    /**
     * 返回數組是否爲空。
     *
     * @return
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 向全部元素後添加一個新元素
     *
     * @param e
     */
    public void addLast(E e) {
        /*if (size == data.length) {
            throw new IllegalArgumentException("AddLast failed. Array is full.");
        }
        data[size] = e;
        size++;*/
        add(size, e);
    }

    public void addFirst(E e) {
        add(0, e);
    }

    /**
     * 在index索引的位置插入一個新元素e
     *
     * @param index
     * @param e
     */
    public void add(int index, E e) {
        if (index < 0 || index > size) {
            throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size.");
        }
        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++;
    }

    /**
     * 擴容
     *
     * @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;
    }

    /**
     * 獲取index索引位置的元素。
     *
     * @param index
     * @return
     */
    public E get(int index) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("Get failed. Index is illgal.");
        }
        return data[index];
    }

    /**
     * 獲取索引爲0的元素。
     *
     * @return
     */
    public E getFirst() {
        return get(0);
    }

    /**
     * 獲取索引爲size-1的元素。
     *
     * @return
     */
    public E getLast() {
        return get(size - 1);
    }

    /**
     * 修改index索引位置的元素爲e。
     *
     * @param index
     * @param e
     */
    public void set(int index, E e) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("Set failed. Index is illegal.");
        }
        data[index] = e;
    }

    /**
     * 查找數組中是否有元素e。
     *
     * @param e
     * @return
     */
    public boolean contains(E e) {
        for (int i = 0; i < size; i++) {
            if (data[i] == e) {
                return true;
            }
        }
        return false;
    }

    /**
     * 查找數組中元素e所在的索引,若是不存在元素e,則返回-1。
     *
     * @param e
     * @return
     */
    public int find(E e) {
        for (int i = 0; i < size; i++) {
            if (data[i] == e) {
                return i;
            }
        }
        return -1;
    }

    /**
     * 從數組中刪除index位置的元素,返回刪除的元素。
     *
     * @param index
     * @return
     */
    public E remove(int index) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("Remove failed. Index is illegal.");
        }
        E ret = data[index];
        for (int i = index + 1; i < size; i++) {
            data[i - 1] = data[i];
        }
        size--;
        if (size == data.length / 4 && data.length / 2 != 0) {
            resize(data.length / 2);
        }
        return ret;
    }

    /**
     * 從數組中刪除第一個元素並返回刪除的元素。
     *
     * @return
     */
    public E removeFirst() {
        return remove(0);
    }

    /**
     * 從數組中刪除最後一個元素並返回刪除的元素。
     *
     * @return
     */
    public E removeLast() {
        return remove(size - 1);
    }

    /**
     * 從數組中刪除元素e。
     *
     * @param e
     */
    public void removeElement(E e) {
        int index = find(e);
        if (index != -1) {
            remove(index);
        }
    }

    public void swap(int i, int j) {
        if (i < 0 || i >= size || j < 0 || j >= size) {
            throw new IllegalArgumentException("Index is Illegal");
        }
        E temp = data[i];
        data[i] = data[j];
        data[j] = temp;
    }

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

}

數組的優劣勢

一、優點
數組擁有高效的隨機訪問能力,只要給出索引,就能夠當即找到對應的元素。
二、劣勢
數組的劣勢體如今插入元素和刪除元素,因爲數組的存儲方式,致使在插入和刪除這兩個操做中大量的元素須要被迫移動,從而影響效率。索引

相關文章
相關標籤/搜索