忘了在哪本書看見過一句話「理解了概念性的東西,你就學會了70%」
回到主題,什麼是陣列?
陣列(array)是一種線性表資料結構。它用一組連續的記憶體空間,來儲存一組具有相同型別的資料
概念中有兩個關鍵的地方:
陣列是一種線性資料結構
陣列中儲存的是連續的記憶體空間和相同型別的資料
什麼是線性資料結構
有資料結構基礎的小夥伴都應該知道,線性結構就是資料排成一條線一樣的資料結構,也就意味著它僅有前後兩個方向,比如佇列、單鏈表、棧等,也是線性結構
與它相對的就是非線性表,最典型的就是樹和圖。他們的特點就是並不是只有前後這種關係
連續的記憶體空間和相同型別的資料
正因為有了這個特性,使得陣列可以進行「隨機訪問」。雖然訪問陣列中某個元素變得很快,但缺點就是在修改(刪除、插入)陣列的時候,操作會變得很麻煩,因為要保證陣列記憶體空間的連續性,所以不得不進行繁瑣的資料移動
假設有乙個長度為5的int型別的陣列var a [5]int,假設給這個陣列分配的記憶體空間首位址是1000,則這個陣列分配的記憶體空間為1000~1019,看下圖
作業系統會為每乙個記憶體單眼分配乙個位址,通過這個位址來訪問記憶體中的資料。當作業系統需要隨機訪問陣列中的某乙個元素時,它會通過下邊這個定址公式來計算出某個元素的儲存位址
a[i]_address = base_address + i * data_type_size
data_type_size:表示陣列中每個元素的大小。比如int型別,它占用的是4個位元組,所以這裡data_type_size就是4
陣列和鍊錶的區別是什麼
通過上邊對陣列的介紹,可以看出來,陣列適合查詢操作。但是查詢的時間複雜度並不為o(1)。即便是排好序的陣列,你用二分查詢,時間複雜度也是o(logn)。所以,陣列支援隨機訪問,根據下標隨機訪問的時間複雜度為o(1)
插入元素
陣列頭部插入元素
在陣列的頭部插入元素,為了保證空間的連續性,需要將陣列中所有的元素向後移一位,然後將待插入元素放入到首部位置
**實現
function insertintohead($elem, $arr)
$arr[0] = $elem;
echo "頭部插入元素之後結果:".php_eol;
print_r($arr);
}
陣列中間插入元素在陣列的中間某個位置插入元素,需要將待插入位置以後的元素均向後移動一位
**實現
function insertintomid($elem, $position, $arr)
$arr[$head] = $value;
echo "頭部插入元素之後結果:".php_eol;
print_r($arr);
}
陣列尾部插入元素在尾部插入元素,不需要移動元素,直接放在當前的末尾元素後邊即可
刪除元素
陣列頭部刪除元素
刪除陣列頭部元素,將所有的元素向前移動一位即可
**實現:
function delhead($arr)
unset($arr[count($arr)-1]);echo "刪除後".php_eol;
print_r($arr);
}
陣列中間刪除元素將待刪除元素後邊的所有元素向前移動一位
**實現:
function delmid($position, $arr)
unset($arr[$len-1]);
echo "刪除後".php_eol;
print_r($arr);
}
陣列尾部刪除元素直接刪除即可,無需移動陣列中的元素
如果在陣列的末尾插入元素,那就不需要移動資料了,這時的時間複雜度為o(1)。但如果在陣列的開頭插入元素,那所有的資料都需要依次往後移動一位,所以最壞時間複雜度是o(n)。因為我們在每個位置插入元素的概率是一樣的,所以平均情況時間複雜度為(1+2+…n)/n=o(n)。刪除元素也是同理
從陣列儲存的記憶體模型上來看,「下標」最確切的定義應該是「偏移(offset)」。前面也說到,如果用a來表示陣列的首位址,a[0]就是偏移為0的位置,也就是首位址。a[k]就表示偏移k個 type_size 的位置,所以計算a[k]的記憶體位址只需要用這個公式
a[k]_address = base_address + k * type_size
但是,如果陣列從1開始計數,那我們計算陣列元素a[k]的記憶體位址就會變為
a[k]_address = base_address + (k-1)*type_size
對比兩個公式,我們不難發現,從1開始編號,每次隨機訪問陣列元素都多了一次減法運算,對於cpu來說,就是多了一次減法指令
陣列作為非常基礎的資料結構,通過下標隨機訪問陣列元素又是其非常基礎的程式設計操作,效率的優化就要盡可能做到極致。所以為了減少一次減法操作,陣列選擇了從0開始編號,而不是從1開始
參考:《資料結構與演算法之美》 《零基礎學資料結構》
往期文章
作業系統基礎(十五)---使用fork系統呼叫建立程序
程序同步之共享內
時間複雜度和空間複雜度
ip協議詳解
it猿圈
不做開始愛好者
php 陣列與資料結構
任意型別的資料,並且可以根據容器中儲存的資料決定容器的容量,打到可以變長的容器結構,比如鍊錶 堆疊和佇列等都是資料結構中常用的形式。在php中,通常都是使用陣列來完成其它語言使用資料結構才能完成的工作。它是若型別語言,在同乙個陣列中就可以儲存多種型別的資料,而且php中的陣列沒有長度限制,陣列儲存資...
算分與資料結構 冒泡思想
冒泡思想的乙個特點是所有的操作都在原陣列中進行,不占用額外的空間。一 氣泡排序 public class bubblesort public static void main string args new bubblesort bubblesort array for int i 0 i 二 冒泡...
Java資料結構與演算法之陣列排序 插入
a,對於隨機順序的資料進行插入排序需要o n2 的時間 b,當資料有序的時候,演算法執行需要o n 時間 c,當資料基本有序的時候,演算法幾乎只需要o n 時間 2 不變性 比outer變數下標號小的資料項都是區域性有序的。3 思路 a 設定乙個outer標籤,用於表示其左邊的元素已經排好,初始位置...