數據結構與算法學習筆記之 從0編號的數組
前言
數組看似簡單,但掌握精髓的卻沒有多少;他既是編程語言中的數據類型,又是最基礎的數據結構;
一個小問題:
為什么數據要從0開始編號,而不是 從1開始呢?
正文
帶著問題進入學習
如何實現隨機訪問?
什么是數組?
數組(array)是一種線性表數據結構,它用一組連續的內存空間來儲存一組具有相同類型的數據。
我們從定義來分析:
?
線性表:
是數據排成像一條線一樣的結構。每個線性表上的數據最多有前后兩個方向。諸如數組,鏈表,隊列,棧等都是線性表結構。
?
連續的內存空間和相同類型的數據:
這個特性是數組“隨機訪問”速度飛快的緣由,這也導致了從數組中刪除、插入數據,為了保證連續性,需要大量的工作量
?
計算機會給每個內存單元分配一個地址,計算機通過地址來訪問內存中的數據。
當計算機隨機訪問數組中的某個元素時,它會首先通過下面的尋址公式,計算出該元素的內存地址:
a[i]_address?=?base_address?+?i?*?data_type_size
data_type_siza表示數組中的每一個元素的大小。如果是int類型的數據,data_type_size為4個字節;
數組和鏈表的區別
鏈表適合插入、刪除,時間復雜度為O(1),數組適合查找,但是這里要注意一下,時間復雜度并不是O(1),即便是排好序的數組,你用二分法查找,時間復雜度也是O(logn),
正確的描述為:數組支持隨機訪問,根據下標隨機訪問的時間復雜度為O(1)
?
低效的“插入”“刪除”
插入操作
假設數組的長度為 n,現在,如果我們需要將一個數據插入到數組中的第 k 個位置,為了把第 k 個位置騰出來,給新來的數據,我們需要將第 k~n 這部分的元素都順序地往后挪一位,下面我們分析一下時間復雜度
如果在數組的末尾插入元素,那就不需要移動數據了,這時的時間復雜度為 O(1),但如果在數組的開頭插入元素,那所有的數據都需要依次往后移動一位,所以最壞時間復雜度是 O(n),因為我們在每個位置插入元素的概率是一樣的,所以平均情況時間復雜度為 (1+2+…n)/n=O(n)
如果數組中的數據是有序的,我們在某個位置插入一個新的元素時,就必須按照剛才的方法搬移 k 之后的數據,如果數組中存儲的數據并沒有任何規律,數組只是被當作一個存儲數據的集合。在這種情況下,如果要將某個數組插入到第 k 個位置
為了避免大規模的數據搬移,我們還有一個簡單的辦法就是
直接將第 k 位的數據搬移到數組元素的最后,把新的元素直接放入第 k 個位置。
?
刪除操作
和插入類似,
如果刪除數組末尾的數據,最好情況時間復雜度為 O(1);
如果刪除開頭的數據,則最壞情況時間復雜度為 O(n);
平均情況時間復雜度也為 O(n)
?
提高效率:
將多次刪除操作中集中在一起執行,可以先記錄已經刪除的數據,但是不進行數據遷移,而僅僅是記錄,當發現沒有更多空間存儲時,再執行真正的刪除操作。這也是 JVM 標記清除垃圾回收算法的核心思想。
?
數組訪問越界問題
C語言中的數據越界是一種未決行為,一般比較難發現的邏輯錯誤。相比之下,Java會有越界檢查。
?
用數組還是容器?
數組先指定了空間大小,容器如ArrayList可以動態擴容。
1.希望存儲基本類型數據,可以用數組
2.事先知道數據大小,并且操作簡單,可以用數組
3.直觀表示多維,可以用數組
4.業務開發,使用容器足夠,開發框架,追求性能,首先數組。
?
為什么數組要從 0 開始編號?
由于數組是通過尋址公式,計算出該元素存儲的內存地址:
a[i]_address = base_address + i * data_type_size
如果數組是從 1 開始計數,那么就會變成:
a[i]_address = base_address + (i-1)* data_type_size
?
以上內容為個人的學習筆記,僅作為學習交流之用。
?
歡迎大家關注公眾號,不定時干貨,只做有價值的輸出
作者:Dawnzhang?
出處:https://www.cnblogs.com/clwydjgs/p/9755971.html
版權:本文版權歸作者
轉載:歡迎轉載,但未經作者同意,必須保留此段聲明;必須在文章中給出原文連接;否則必究法律責任
小舟從此逝,江海寄余生。 --狐貍
轉載于:https://blog.51cto.com/13681587/2307407