以前學習過了數組的靜態實現方法,同時將數組的全部有可能實現的方法都統一實現了一遍,以後支持了泛型的相關java
概念,接下來就是如何對數組進行擴容的操做也就是實現動態數組。算法
private void resize(int newcapacity){ E[] newdata = (E[]) new Object[newcapacity]; for (int i = 0; i < newcapacity; i++) { newdata[i] = data[i]; } data = newdata; }
在此處,咱們寫了一個關於resize的操做,其原理就是對就數組容量的擴容,擴容其原來的二倍。數組
同理,咱們還能夠進行對刪除操做的優化,若是刪完數據後,數組的容量有一半可能是不用的空間,咱們就能夠進行刪學習
掉一半的操做。優化
public E remove(int index) { if (index < 0 || index > size) { throw new IllegalArgumentException("require index >= 0 and index > size!"); } E ret = data[index]; for (int i = index + 1; i < size; i++) { data[i - 1] = data[i]; } size--; data[size] = null; // loitering Objects != memory leak if(size == data.length / 2){ resize(data.length/2); } return ret; }
注意代碼的第11,12行 進行了優化。ui
至此,咱們就把數組的動態的實現整理完畢了。atom
接下來,我簡單的描述一下時間複雜度的分析。spa
O(1) O(n) O(lgn) O(nlogn) O(n^2)3d
大O是描述的算法運行時間和輸入數據之間的關係。code
O(n)中 n表示的是元素的個數 算法和n呈線性關係。
那麼O(n^2)則表示的是 成二次方的關係。
針對於不一樣的算法,咱們須要針對不一樣的變量進行變量控制,來肯定這個算法是不是最快的。
同理,刪除操做也是相應的時間複雜度。
在看完時間複雜度以後,咱們引入一個resize的時間複雜度分析。
對於添加的時間複雜度分析,咱們能夠看到,resize的時間複雜度分析是O(n),那麼咱們按最壞時間複雜度分析,
咱們就將添加的時間複雜度算爲O(n),可是並非每次添加元素咱們都要resize的 ,因此假設capacity = n,n+1次
addLast,觸發resize,總共進行2n+1次基本操做平均,每次addLast操做,進行兩次基本操做。這樣均攤計算,時間復
雜度是O(1)的!,同理removeLast()的時間複雜度也是O(1)的,可是,若是咱們綜合去看待這個方法時,就會出現問
題。在填滿數據後,我調用addLast()方法時,須要擴容,緊接着我又調用removeLast()方法,又開始縮容,一直這
樣下去,時間複雜度一直是O(n),這樣就產生了時間複雜度震盪。出現的緣由是:removeLast()時,過於着急,咱們
可讓他懶惰一些,也就是說能夠在等到size == capacity/4時,纔將capacity減半。
這樣,咱們本身寫完的動態數組就完成了!