數據結構---->數組

 

1.什麼是數組?

           數組是一種線性的數據結構.它同一組連續的內存空間,來存儲一組具備相同類型的數據。數組

簡單說明幾點:數據結構

          (1).線性表:就是數據排成像一條線同樣的結構。每一個線性表的數據最多隻有前和後兩個方向。除了數組,鏈表,隊列,棧等也是線性表結構。spa

              

                對立的是非線性表,好比二叉樹,堆,圖等之因此被稱爲非線性,是由於,在非線性表中,數據之間並不簡單的先後關係。code

             

         (2).數組是連續的內存空間和相同的數據類型。正是由於這樣數據的隨機訪問的速度很快,有利就有弊,好比在數組中刪除和插入一個數據,爲了保證連續性,就須要大量的數據搬用   的工做。blog

 

2.說到數據的訪問,那你知道數組是如何實現根據下標隨機訪問數組元素的嗎?

      咱們拿一個長度爲 10 的 int 類型的數組 int[] a = new int[10] 來舉例。在我畫的這個圖 中,計算機給數組 a[10],分配了一塊連續內存空間 1000~1039,其中,內存塊的首地址 爲 base_address = 1000。索引

      咱們知道,計算機會給每一個內存單元分配一個地址,計算機經過地址來訪問內存中的數據。 當計算機須要隨機訪問數組中的某個元素時,它會首先經過啊a[i]_address=base-address+i * data_type_size 的尋址公式,計算出該元素 存儲的內存地址.隊列

其中 data_type_size 表示數組中每一個元素的大小。咱們舉的這個例子裏,數組中存儲的是 int 類型數據,因此 data_type_size 就爲 4 個字節。這個公式很是簡單,我就很少作解釋 了。內存

 ,數組支持隨機訪問,根據下標隨機訪問的時間複雜度爲 O(1)ci

3.數組爲了保持內存數據的連續性,會致使插入,刪除這兩個操做的效率比較低,那爲何會致使低效,有什麼改進的方法?

      假設數組長度是n ,如今須要將一個數據插入到數組的第K個位置,爲了吧k位置挪出來,給新來的數據,咱們須要吧k—n 這部分的元素順序日後移動一位,那麼時間的複雜度是多少呢?element

下面咱們來分析一下:

     若是在數組的末尾插入元素,那就不須要移動元素了,那麼時間的複雜度爲O(1),若是在數組的開頭插入元素,那麼全部的數據須要一次向後移動一位,因此最壞的時間複雜度是O(N),由於咱們在每一個位置插入元素的機率是同樣的,因此平均時間複雜度(1+2+。。。。+n)/n=O(n)

     若是數組中的數據是有序的,咱們在某一個位置插入一個新元素時,就必須搬移k以後的數據。可是數組中的數據是無序的,沒有規律,數據只是存儲數據的集合。在這種狀況下,若是要將元素插入到K位置,爲了不大規模的數據移動,之間將K位置的數據搬移到數組元素的最後,把新的元素之間放到第K個位置。刪除的操做,爲了內存的連續性,也須要移動數據,和插入相似,若是刪除數組末尾的數據,則最好狀況時間複雜度爲 O(1);若是刪除開頭的 數據,則最壞狀況時間複雜度爲 O(n);平均狀況時間複雜度也爲 O(n)。

    實際上,在某些特殊場景下,咱們並不必定非得追求數組中數據的連續性。若是咱們將屢次 刪除操做集中在一塊兒執行,刪除的效率是否是會提升不少呢?

    咱們繼續來看例子。數組 a[10] 中存儲了 8 個元素:a,b,c,d,e,f,g,h。如今,我 們要依次刪除 a,b,c 三個元素,爲了不 d,e,f,g,h 這幾個數據會被搬移三次,咱們能夠先記錄下已經刪除的數據。 每次的刪除操做並非真正地搬移數據,只是記錄數據已經被刪除。當數組沒有更多空間存 儲數據時,咱們再觸發執行一次真正的刪除操做,這樣就大大減小了刪除操做致使的數據搬移。

 

4.容器可否徹底替換數組?

(1).在Java中提供的容器類,ArrayList最大的優勢就是能夠將不少數組操做的細節封裝起來,便於調用,另外一個優勢是支持動態擴容。

(2).數組自己在定義的時候預先指定了大小,由於須要分配連續的內存空間,若是咱們分配了大小爲10的數組,當第11個元素須要存儲到數組當中時,咱們須要從新分配一塊更大的空間,將原來的數據複製過去,而後將新的數據插入。

(3).使用ArrayList,咱們徹底不須要關心底層的擴容邏輯,ArrayList 已經幫咱們實現好了,存儲空間不夠的時候,會將空間自動擴容1.5倍的大小。

(4).ArrayList沒法存儲基本的數據類型,(8種基本數據類型),而是引用類型,因此基本數據類型,能夠選用數組.

5.代碼實現數組的增長刪除查詢的操做?

public class ArrayTest {

    private Object[] elementData; //定義一個空的數組

    private int size; //數組的大小

    //初始話數組的大小
    public ArrayTest() {
        elementData = new Object[10];
    }

    /**
     * 增長元素
     */
    public boolean add(Object obj) {
        ensureCapacityInternal(size + 1); 
        elementData[size++] = obj;
        return true;

    }
    //主要的判斷數組是否須要擴容
    private void ensureCapacityInternal(int minCapaCity) {

        if (minCapaCity - elementData.length > 0) {
            grow(minCapaCity);
        }
    }
    //數組擴容的操做
    private void grow(int minCapaCity) {
        int oldcapaCity = elementData.length;
        int newCapaCity = oldcapaCity + oldcapaCity >> 1;
        if (newCapaCity - minCapaCity < 0) {
            newCapaCity = minCapaCity;
        }
        if (newCapaCity - Integer.MAX_VALUE > 0) {
            newCapaCity = Integer.MAX_VALUE;
        }
        elementData = Arrays.copyOf(elementData, newCapaCity);
    }

    /**
     * 刪除數組中的元素,經過索引
     */
    public Object remove(int index) {
        rangCheck(index);
        Object oldValue = elementData[index];
        int moveNum = size - index - 1; //數組移動的次數
        if (moveNum > 0) {
            System.arraycopy(elementData, index + 1, elementData, index, moveNum);
        }
        elementData[--size] = null;
        return oldValue;
    }
    //查詢指定索引下數組的元素
    public Object get(int index) {
        rangCheck(index);
        return elementData[index];
    }

    private void rangCheck(int index) {
        if (index < 0 && index > size) {
            throw new IndexOutOfBoundsException("index:" + index + "size:" + size);
        }
    }


    public static void main(String[] args) {
        ArrayTest arrayTest = new ArrayTest();
        for (int i = 0; i < 10; i++) {
            arrayTest.add("第" + i + "個元素");
        }
        arrayTest.remove(3);
        for (int i = 0; i < 9; i++) {
            System.out.println(arrayTest.get(i));
        }
    }
}

 

6.總結:

數組用一塊連續的內存空 間,來存儲相同類型的一組數據,最大的特色就是支持隨機訪問,但插入、刪除操做也所以 變得比較低效,平均狀況時間複雜度爲 O(n)。在平時的業務開發中,咱們能夠直接使用編 程語言提供的容器類,可是,若是是特別底層的開發,直接使用數組可能會更合適。

 

 

相關文章
相關標籤/搜索