4、數組

什麼是數組?

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

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

非線性表,數據之間並不是簡單的前後關係,比如二叉樹,堆,圖等。

2.連續的內存空間和相同類型的數據
優點:隨機訪問
缺點:插入刪除將做大量數據搬移

如何實現隨機訪問?

計算機會給每個內存單元分配一個地址,計算機通過地址來訪問內存中的數據。當計算機需要隨機訪問數組中的某個元素時,會首先通過尋址公式,計算出該元素存儲的內存地址
a[i]_address = base_address + i*data_type_size

查找的時間複雜度

鏈表適合插入,刪除,時間複雜度爲O(1);數組適合查找,查找時間複雜度爲O(1);
上面這種說法是錯誤的,數組是適合查找操作,但是查找的時間複雜度並不爲O(1),即便是排好序的數組,你用二分查找,時間複雜度也是O(logn)。所以,應該這樣說,數組支持隨機訪問,根據下標隨機訪問的時間複雜度爲O(1)

低效的”插入”和”刪除”

插入:

數組末尾插入:時間複雜度爲O(1)
數組開頭插入:時間複雜度爲O(n)
因爲我們在每個位置插入元素的概率一樣,所以平均情況時間複雜度爲(1+2+…n)/n=O(n)

優化:數組若無序,插入新的元素時,可以將第K個位置元素移動到數組末尾,把新的元素,插入到第K個位置,此處複雜度爲O(1)

刪除:

和插入一樣,最好O(1)最壞O(n)平均O(n)
提高刪除效率:將多次刪除操作中集中在一起執行,可以記錄下已經被刪除的數據,每次的刪除操作並不是搬移數據,只是記錄數據已經被刪除,當數組沒有更多的存儲空間時,再觸發一次真正的刪除操作。即JVM標記清除垃圾回收算法

數組訪問越界問題:

C語言中的數據越界是一種未決行爲,是編程語言和編譯器都相關的,一般比較難發現的邏輯錯誤。相比之下,Java會有越界檢查

容器能否完全替代數組

容器的優勢:

ArrayList最大的優勢就是可以將很多數組操作的細節封裝起來,比如前面提到的數組插入,刪除數據時需要搬移其他數據等,還有一個就是支持動態擴容。

數組本身在定義的時候需要預先指定大小,因爲需要分配連續的內存空間。如果我們申請了大小爲 10 的數組,當第 11 個數據需要存儲到數組中時,我們就需要重新分配一塊更大的空間,將原來的數據複製過去,然後再將新的數據插入。

如果使用 ArrayList,我們就完全不需要關心底層的擴容邏輯,ArrayList 已經幫我們實現好了。每次存儲空間不夠的時候,它都會將空間自動擴容爲 1.5 倍大小。

不過,這裏需要注意一點,因爲擴容操作涉及內存申請和數據搬移,是比較耗時的。所以,如果事先能確定需要存儲的數據大小,最好在創建 ArrayList 的時候事先指定數據大小。

使用數組的情況:

  1. Java ArrayList無法存儲基本類型,比如int,long,需要封裝爲Integer,Long類,而自動裝箱和拆箱則有一定的性能消耗,所以如果特別關注性能,或者希望使用基本類型,就可以選用數組

  2. 如果數據大小事先已知,並且對數據的操作非常簡單,用不到ArrayList提供的大部分方法,也可以選用數組

  3. 當要表示多維數組時,用數組往往會更加直觀。比如Object[][] array;而用容器的話則需要這樣定義:ArrayList array。

總結:

對於業務開發,直接使用容器就足夠了,省時省力。畢竟損耗一丟丟性能,完全不會影響到系統整體的性能。但如果你是做一些非常底層的開發,比如開發網絡框架,性能的優化需要做到幾隻,這個時候數組就會優於容器,稱爲首選。

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