演算法快學筆記(二):陣列與連結串列
1. 說明
當程式需要將資料儲存到記憶體時,計算機會給你一個儲存地址。需要存
儲多項資料時,有兩種基本方式——陣列和連結串列。但它們並非都適用於所有的情形,因此知道它們的特性很重要。本文將對陣列與連結串列的原理與優缺點進行總結。
2. 陣列
使用陣列儲存多個元素的時候,陣列中元素的地址時刻都是挨在一起的,為了便於理解,以看電影為例進行說明。
你和你小夥伴的關係都非常的好,如果一起看電影必須要座位要挨在一起,你先和兩個小夥伴去看電影,到了電影院只坐有連續三個空位的地方(陣列初始化)。找到地方就坐後又來了一位朋友,但原來坐的地方沒有空位置,這時只能重新找一個可坐下所有人的地方(陣列插入新元素
真是太麻煩了。同樣,在陣列中新增/刪除元素也很麻煩。因此陣列新增/刪除元素的速度都會很慢。
對於新增元素的一種解決之道是“預留座位”:即便你們現在只有3個小夥伴,也請計算機提供10個位置,以防臨時有朋友來的情況。這樣,只要小夥伴不超過10個,就無需轉移。
該方案存在兩個缺點。
- 你額外請求的位置可能根本用不上,這將浪費記憶體。你沒有使用,別人也用不了。
- 待辦事項超過10個後,你還得轉移。
3. 連結串列
連結串列的每個元素都儲存了下一個元素的地址,從而使一系列隨機的記憶體地址串在一起,因此連結串列中的元素可儲存在記憶體的任何地方,當新增/刪除元素時其他的元素都不需要移動。同樣以看電影為例對連結串列進行說明。
假設你與10位朋友去看一部很火的電影。你們11人想坐在一起,但看電影的人較多,沒有11個在一起的座位,如果是陣列的解決方式,這個電影就看不了了,因為實在沒有這麼多空的位置是在一起的。連結串列的解決方式是“既然這樣,我們分開來坐,但是為大家之間還可能會聯絡,因此每個人都依次記得下一個人的座位號,例如A記得B的座位號是008,B記得C的座位號是102…”,因此,只要有足夠的記憶體空間,就能為連結串列分配記憶體
4. 陣列與連結串列的查詢
從看電影的例子可以看出,使用連結串列的方式,解決入場觀看(初始化),以及中途人員變動(新增/刪除)是一個比較好的方案,但是如果用來找你的小夥伴了?考慮以下兩種操作
4.1 全部查詢
- 陣列方式:由於所有小夥伴都做在一起,只要找到第一個,其他的就都能找到。
- 連結串列方式:雖然小夥伴都是分散做的,但是由於每個小夥伴都知道下一個小夥伴的座位號,因此要找全部小夥伴也比較方便
4.2 隨機查詢
假設10個小夥伴的入場看電影的時候,是按照年齡從小到大的順序入場的,你突然要找年齡最大的那個小夥伴。
- 陣列方式:由於所有小夥伴都做在一起,找到第一個人後,他的座位號+10就是年齡最大的那個小夥伴。
- 連結串列方式:由於小夥伴都是分散坐的,所以你只能從第一個人問第二個人的座位號,到第二個人那邊後,問他第三個人的座位號,以此類推。
通過上面的例子可以看出,在隨機讀取的場景:
- 需要隨機地讀取元素時,陣列的效率很高,因為可迅速找到陣列的任何元素。
- 在連結串列中元素並非靠在一起的,你無法迅速計算出第i個元素的記憶體地址,而必須先訪問第一個元素以獲取第二個元素的地址,再訪問第二個元素以獲取第三個元素的地址,以此類推,直到訪問第i個元素。
5. 總結
- 需要儲存多個元素時,可使用陣列或連結串列。
- 陣列的元素都在一起。
- 連結串列的元素是分開的,其中每個元素都儲存了下一個元素的地址。
- 陣列的隨機讀取速度很快。
- 連結串列的插入和刪除速度很快。
- 在同一個陣列中,所有元素的型別都必須相同(都為int、 double等)。