一、陣列(array)是一種線性表資料結構。它用一組連續的記憶體空間,來儲存一組具有相同型別的資料。
a[i]_address = base_address + i * data_type_size
注:data_type_size 表示陣列中每個元素的大小
陣列和鍊錶的區別
鍊錶適合插入、刪除,時間複雜度 o(1)。
陣列是適合查詢操作,但是查詢的時間複雜度並不為 o(1)。即便是排好序的陣列,你用二分查詢,時間複雜度也是 o(logn)。所以,正確的表述應該是,陣列支援隨機訪問,根據下標隨機訪問的時間複雜度為 o(1)。
二、插入和刪除操作
1、插入
如果在陣列的末尾插入元素,那就不需要移動資料了,這時的最好時間複雜度為 o(1)。
但如果在陣列的開頭插入元素,那所有的資料都需要依次往後移動一位,所以最壞時間複雜度是 o(n)。
因為我們在每個位置插入元素的概率是一樣的,所以平均情況時間複雜度為 (1+2+…n)/n=o(n)
在這種情況下,如果要將某個資料插入到第 k 個位置,為了避免大規模的資料搬移,我們還有乙個簡單的辦法就是,直接將第 k 位的資料搬移到陣列元素的最後,把新的元素直接放入第 k 個位置。
2、刪除
如果刪除陣列末尾的資料,則最好情況時間複雜度為 o(1);
如果刪除開頭的資料,則最壞情況時間複雜度為 o(n);
平均情況時間複雜度也為 o(n)。
為了避免 d,e,f,g,h 這幾個資料會被搬移三次,我們可以先記錄下已經刪除的資料。每次的刪除操作並不是真正地搬移資料,只是記錄資料已經被刪除。當陣列沒有更多空間儲存資料時,我們再觸發執行一次真正的刪除操作,這樣就大大減少了刪除操作導致的資料搬移。
警惕陣列的訪問越界問題
int
main
(int argc,
char
* ar**)
;for
(; i<=
3; i++
)return0;
}
這段**的執行結果並非是列印三行「hello word」,而是會無限列印「hello world」
因為,陣列大小為 3,a[0],a[1],a[2],而我們的**因為書寫錯誤,導致 for 迴圈的結束條件錯寫為了i<=3而非i<3,所以當 i=3 時,陣列 a[3]訪問越界。
答:為什麼大多數程式語言中,陣列要從 0 開始編號,而不是從 1 開始呢?
從陣列儲存的記憶體模型上來看,「下標」最確切的定義應該是「偏移(offset)」。前面也講到,如果用 a 來表示陣列的首位址,a[0]就是偏移為 0 的位置,也就是首位址,a[k]就表示偏移 k 個 type_size 的位置,所以計算 a[k]的記憶體位址只需要用這個公式:
a[k]_address = base_address + k * type_size
a[k]_address = base_address + (k-1) * type_size
對比兩個公式,我們不難發現,從 1 開始編號,每次隨機訪問陣列元素都多了一次減法運算,對於 cpu 來說,就是多了一次減法指令。
資料結構與演算法學習筆記
演算法基礎篇 第一章 演算法概述 首先了解一下基本的概念 1.1 什麼是演算法呢?從字面意義上理解,演算法就是用於計算的方法,用這種方法達到預期的結果。通俗的講,演算法可以理解為乙個完整的解題步驟,由一些基本的運算和規定的運算順序組成。通過這樣的解題步驟可以解決特定的問題。演算法可以抽象出5個特徵 ...
資料結構與演算法學習筆記(一)
資料 計算機操作的物件 資料元素 組成資料的基本基本單位 資料項 乙個資料元素可以由若干個資料項組成 資料物件 性質相同的資料元素的集合 資料結構 是相互之間存在一種或多種特定關係的資料元素的集合 資料型別 1.原子型別 不可以在分解的基本型別,包括整型,字元型 2.結構型別 由若干個型別組合而成 ...
資料結構與演算法學習筆記3
最好情況時間複雜度 最壞情況時間複雜度 平均情況時間複雜度 均攤時間複雜度 例 在乙個無序的陣列 array 中,查詢變數 x 出現的位置。如果沒有找到,就返回 1 n表示陣列array的長度 intfind int array,int n,int x return pos 時間複雜度 o n nn...