『數據結構與算法』—— 數組

定義

數組(Array)是一種線性表數據結構。它用一組連續的內存空間,來存儲一組具有相同類型的數據。

線性表

顧名思義,線性表就是數據排成像一條線一樣的結構。每個線性表上的數據最多隻有前和後兩個方向。其實除了數組,鏈表、隊列、棧等也是線性表結構。

連續內存,類型相同

我們知道,計算機會給每個內存單元分配一個地址,計算機通過地址來訪問內存中的數據。當計算機需要隨機訪問數組中的某個元素時,它會首先通過下面的尋址公式,計算出該元素存儲的內存地址:

a[i]_address = base_address + i * data_type_size

優劣

優點顯而易見,其時間複雜度僅僅爲 O(1),但是對於插入或者刪除,都需要通過平移數組來完成操作,這就意味着最壞時間複雜度爲 O(n),如果容量還需要進行擴容,這是相當耗時的。

個人總結

  1. Java List 無法存儲基本類型,都需要封住成 Integer 或者 Long 類,而裝箱和拆箱是有很大的性能消耗的。
  2. 如果數據大小事先已知,並且對數據的操作非常簡單,用不到 ArrayList 提供的大部分方法,也可以直接使用數組。

例子

  1. 普通數組封裝(不支持擴容)
class Array {
    int data[];
    int count;
    int n;

    Array(int capacity) {
        data = new int[capacity];
        count = 0;
        n = capacity;
    }

    boolean add(int index, int value) {
        if (count >= n) {
            System.out.println("容量達到最大值");
            return false;
        }
        if (index > count) {
            System.out.println("下標越界");
            return false;
        }
        // 從屁股開始,往後移動,將 index 位置空出來
        for (int i = count; i > index; i--) {
            data[i] = data[i - 1];
        }
        data[index] = value;
        count++;
        System.out.println("插入成功:\tvalue:\t" + value + ":\tindex:\t" + index);
        System.out.println("data:\t" + toString());
        return true;
    }

    int get(int index) {
        if (index >= count) {
            return -1;
        }
        System.out.println("value:\t" + data[index]);
        return data[index];
    }

    boolean delete(int index) {
        if (index >= count) {
            System.out.println("下標越界");
            return false;
        }
        for (int i = index; i < count - 1; i++) {
            data[i] = data[i + 1];
        }
        data[count - 1] = 0;
        count--;
        System.out.println("刪除成功 data:\t" + toString());
        return true;
    }

    @Override
    public String toString() {
        return Arrays.toString(data);
    }

    public static void main(String[] args) {
        Array array = new Array(10);
        array.add(0, 1);
        array.add(1, 2);
        array.add(2, 3);
        array.add(3, 4);
        array.add(4, 5);
        array.add(5, 6);
        array.add(6, 7);
        array.add(7, 8);
        array.add(8,9);
        array.add(9,10);
        array.delete(9);
        System.out.println("get value:\t" + array.get(3));
    }
}

輸出結果:

插入成功:   value:  1:  index:  0
data:   [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
插入成功:   value:  2:  index:  1
data:   [1, 2, 0, 0, 0, 0, 0, 0, 0, 0]
插入成功:   value:  3:  index:  2
data:   [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]
插入成功:   value:  4:  index:  3
data:   [1, 2, 3, 4, 0, 0, 0, 0, 0, 0]
插入成功:   value:  5:  index:  4
data:   [1, 2, 3, 4, 5, 0, 0, 0, 0, 0]
插入成功:   value:  6:  index:  5
data:   [1, 2, 3, 4, 5, 6, 0, 0, 0, 0]
插入成功:   value:  7:  index:  6
data:   [1, 2, 3, 4, 5, 6, 7, 0, 0, 0]
插入成功:   value:  8:  index:  7
data:   [1, 2, 3, 4, 5, 6, 7, 8, 0, 0]
插入成功:   value:  9:  index:  8
data:   [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
插入成功:   value:  10: index:  9
data:   [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
刪除成功 data:  [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
value:  4
get value:  4
  1. 支持擴容的數組
class GenericArray<T> {
    T[] data;
    int size;

    GenericArray(int capacity) {
        data = (T[]) new Object[capacity];
        size = 0;
    }

    GenericArray() {
        this(10);
    }

    void checkIndex(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("下標越界");
        }
    }

    void resize(int newSize) {
        T[] newData = (T[]) new Object[newSize];
        for (int i = 0; i < size; i++) {
            newData[i] = data[i];
        }
        System.out.println("擴容 capacity:\t" + newSize);
        data = newData;
    }

    T get(int index) {
        checkIndex(index);
        return data[index];
    }

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

    void set(int index, T t) {
        checkIndex(index);
        data[index] = t;
        System.out.println("set value:" + " index: " + index + " value: " + t);
        System.out.println("data: " + toString());
    }

    int getCapacity() {
        return data.length;
    }

    int getCount() {
        return size;
    }

    boolean contains(T t) {
        for (int i = 0; i < size; i++) {
            if (data[i] == t) {
                return true;
            }
        }
        return false;
    }

    int find(T t) {
        for (int i = 0; i < size; i++) {
            if (data[i] == t) {
                return i;
            }
        }
        return -1;
    }

    void add(int index, T t) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException("下標越界");
        }
        if (size == data.length) {
            resize(2 * size);
        }
        for (int i = size; i > index; i--) {
            data[i] = data[i-1];
        }
        data[index] = t;
        size ++;
        System.out.println("add data: " + " index: " + index + " value: " + t);
        System.out.println("data: " + toString());
    }

    void addFirst(T t) {
        add(0, t);
    }

    void addLast(T t) {
        add(size, t);
    }

    T remove(int index) {
        checkIndex(index);
        T t = data[index];
        for (int i = index; i < size - 1; i++) {
            data[i] = data[i + 1];
        }
        data[size-1] = null;
        size--;
        if (size == data.length / 4 && data.length / 2 != 0) {
            resize(data.length / 2);
        }
        System.out.println("remove data: " + " index: " + index + " value: " + t);
        System.out.println("data: " + toString());
        return t;
    }

    @Override
    public String toString() {
        return Arrays.toString(data);
    }

    public static void main(String[] args) {
        GenericArray<String> data = new GenericArray<String>(6);
        data.addLast("1");
        data.addLast("2");
        data.addLast("3");
        data.addLast("4");
        data.addLast("5");
        data.addLast("6");
        data.addLast("7");

        data.remove(data.getCount()-1);
        data.remove(data.getCount()-1);
        data.remove(data.getCount()-1);
        data.remove(data.getCount()-1);
    }
}

輸出結果:

add data:  index: 0 value: 1
data: [1, null, null, null, null, null]
add data:  index: 1 value: 2
data: [1, 2, null, null, null, null]
add data:  index: 2 value: 3
data: [1, 2, 3, null, null, null]
add data:  index: 3 value: 4
data: [1, 2, 3, 4, null, null]
add data:  index: 4 value: 5
data: [1, 2, 3, 4, 5, null]
add data:  index: 5 value: 6
data: [1, 2, 3, 4, 5, 6]
擴容 capacity:    12
add data:  index: 6 value: 7
data: [1, 2, 3, 4, 5, 6, 7, null, null, null, null, null]
remove data:  index: 6 value: 7
data: [1, 2, 3, 4, 5, 6, null, null, null, null, null, null]
remove data:  index: 5 value: 6
data: [1, 2, 3, 4, 5, null, null, null, null, null, null, null]
remove data:  index: 4 value: 5
data: [1, 2, 3, 4, null, null, null, null, null, null, null, null]
擴容 capacity:    6
remove data:  index: 3 value: 4
data: [1, 2, 3, null, null, null]

參考自極客時間

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