什麼?
數組是一種線性表數據結構,用一組連續的內存空間來存儲具有同一種數據類型數據。
特點
- 數組支持隨機訪問。
- 數組的 插入 和 刪除 操作比較低效。
隨機訪問
根據尋址公式:array[i] = base_address+i*data_type_size迅速找到對應下標 i 中數據,隨機訪問時間複雜度爲O(1)。
插入操作
- 最好情況:插在末尾,時間複雜度爲O(1);
- 最壞情況:插在開頭,時間複雜度爲O(n);
- 一般情況,插在中間k位置:
- 如果數組存放數據有特定的順序或關聯,則涉及插入後數據的移動,考慮概率的情況,平均時間複雜度爲O(n);
- 如果數組僅存放數據,數據沒有特定順序,則可以將k位數據移到最後,再插入k位,時間複雜度位O(1);
刪除操作
- 最好情況:刪除末尾,O(1);
- 最壞情況:刪除開頭,O(n)
- 一般情況,刪除中間k位置:
1. 無論數組存放數據是否有序,刪除k位的元素後需要移動k+1~n的數據,頻繁的刪除操作會導致頻繁的數據搬移工作;
2. 如果不追求數組中存放數據的連續性,可以將多次刪除操作集中到某一次執行,每次刪除操作僅僅做刪除標記,每次刪除記錄下被刪除的數據,當數組沒有更多的空間,則可以觸發一次真正的刪除操作,這樣就可以減少刪除產生的數據搬移的工作。
數組越界
數組按照下標的隨機訪問,本質是訪問基於base_address做偏移量的計算得到的內存地址,只要這塊內存可以使用,那麼即使下標已超出數組長度,程序也不會報錯。例如下面的C程序:
int main(int argc, char* argv[]){
int i = 0;
int arr[3] = {0};
for(; i<=3; i++){
arr[i] = 0;
printf("hello \n");
}
return 0;
}
但是不是所有的高級語言如C一樣把檢查數組越界的工作丟給程序員,Java就對數組越界問題做了檢測,會拋出 java.lang.ArrayIndexOutOfBoundsException
異常。
public static void main(String[] args) {
int[] arr = new int[3];
arr[0]=11;
for(int i=0;i<=3;i++){
arr[i]=0;
System.out.println("hello ");
}
}
Java中容器類ArrayList和數組
- ArrayList 將很多數組操作的細節封裝了起來,比如數組的插入、刪除時需要搬移其他數據等;
- ArrayList支持動態擴容,當空間不夠時會自動擴容至當前的1.5倍,擴容涉及到內存空的申請等操作比較耗時,所以最好可以提前指定大小。
- ArrayList無法存儲基本數據類型,例如int、double等,需要用封裝類,這裏就涉及到自動裝箱和拆箱或有一定的性能損耗,如果特別關注性能或者希望使用基本類型,就可以用數組。
- 多爲數組Object[][]相比ArrayList<ArrayList< Object > > 更加直觀。
- 業務開發中,我們可以直接使用容器類,如果是特別底層的開發,直接使用數組可能會更合適。
熄燈
這下應該指導爲什麼一般數組下標不從1開始而從0開始了吧!下標其實就是偏移量,如果從1開始的話尋址的時候還需要做i-1
這樣的操作,這就需要執行一次減法指令,像這麼基礎的數據結構,當然追求極致的性能,所以從0開始比較合理。(其實第一個人是從0開始的,後面大家都跟着用習慣了!!!)