大家好呀,我是帥蛋。瞎起題目的嘴強王者,亂寫界的無冕之王。
提到陣列,想必大家夥兒都不陌生。說不定已經昂起腦瓜抖著腿,小眼神兒斜著來一句:“就那個隨隨便便用腳趾甲就能學會的陣列?”
陣列,你確定很簡單?
自信點,語氣肯定點,陣列確實很簡單,但越是簡單的東西在細節上越是要注意,這就是我要寫陣列的初衷。
當然開始之前,你要確定你先看過下面這篇:
保姆級教學!徹底學會時間複雜度和空間複雜度
。。。
文章導讀
陣列,一種基礎的的線性資料結構。不管寫什麼程式碼基本上都會用到陣列,它也是面試中面試官喜歡提問的高頻問題。
鑑於它勞模的身份,
對陣列的考察基本都是考察程式碼方面
的問題。
但是萬變不離其宗,解決陣列方面問題的萬能鑰匙,其實就是深刻的認識陣列本身的深淺。
什麼是陣列?
首先什麼是陣列?
陣列是一種基礎的
線性資料結構
,它是用
連續的一段記憶體空間,來儲存相同資料型別
資料的集合。
這裡面有兩個重點:
線性資料結構
連續記憶體儲存相同資料型別
線性資料結構
線性資料結構,顧名思義,像線一樣的資料結構,又硬又直的典型代表。
線性資料結構是有限的,它是某類元素的集合並且記錄著元素之間的一組順序關係,除了首尾之外,其餘元素之間有且只有一個前驅和後繼
。
除了陣列以外,像單鏈表、棧、佇列等也是典型的線性資料結構。
連續記憶體儲存的相同資料型別
以一個長度為 6 的 int 型別的陣列為例,理解一下“連續記憶體儲存相同資料型別”陣列的樣砸。
上圖中的計算機給陣列 a 分配了一塊連續的記憶體空間 1000 - 1005,首地址 address[0] = 1000。
因為連續,且對於陣列來說下標從 0 開始的,所有對於陣列中的每個元素來說,它的記憶體地址就很好計算:
address[i] = address[0] + i
陣列的操作
從上面可以看出,連續記憶體儲存使得陣列有一個天然的優勢,這個優勢就是可以根據下標,快速的隨意訪問任意一個位置的數**組元素。**
因為陣列可以保證不管你訪問哪個元素,只要給出下標,只需進行一次操作,就可以定位到元素的位置,從而拿出這個位置上的值。
這步操作的時間複雜度就是 O(1)。
當然 God 是公平的,
在查詢上讓陣列當了快男,那必定讓它在插入和刪除上加上“持久”技能點。
在這你要明白,持久意味著花的時間多(低效)。這麼看來,在資料結構與演算法中,秒男成了褒義詞。
這種插入和刪除的“持久”,是如何產生的呢?
這還是要從“連續記憶體儲存”上找原因,真所謂快也它,慢也它。
連續的記憶體使得在插入或者刪除的元素的時候,其它元素也要相應的移動。
比如我們在下標為 2 的位置上插入一個元素 29:
為了保持連續記憶體儲存,在下標為 2 的位置上插入 29,原先 2 - 5 下標位置上元素都要向後一步走,可以看出這一步操作的時間複雜度為 O(n)。
當然在這我必須要強調一點的是,插入的時間複雜度其實根據情況的不同而不同,在這裡主要因為 懶 手疼,沒有都列出來,畢竟我的臭寶們是最聰明噠。
一般我都是按照
最壞情況時間複雜度
來算。對於插入來說,最好的情況肯定是插在末尾,這樣所有的元素都不用動,時間複雜度為 O(1),那最壞的情況就是在陣列的開頭插入,這樣所有的元素都要動,時間複雜度就成了 O(n),請大家一定要注意。
對刪除來說,和插入操作也差不多,比如我們刪除下標為 2 位置上的元素。
刪除了下標 2 位置上的數字 a[2], 原來下標 3 - 5 位置上的元素統統向前一步走。
同樣對於刪除來說,最好情況是刪除末尾的元素,時間複雜度為 O(1),最壞的情況是刪除首位的元素,時間複雜度是 O(n)。
陣列的查詢、插入和刪除這 3 個操作講完以後,還有最後一點提醒一下大家,在做陣列類問題的時候要注意
陣列越界
的問題。
陣列越界,簡單來說就是對於一個大小為 n 的陣列,它的下標應是 0 到 n-1,對這 n 個位置的元素之外的訪問,就是非法的,這就叫做“越界”。
比如對於下面這兩行程式碼:
lst = [1,2,3,4]print(lst[4])
編譯一下,就會提示 IndexError : list index out of range。
臭寶們平時寫陣列的時候一定要注意,不然一不小心就 out 了。
到這裡,簡單的陣列就講完啦,能忍著看到這的都是真愛呀。碼字碼的手都痛啦,
點贊和快樂
給我刷起來~
我是帥蛋,咱們下次見啦~