陣列在增刪方面比連結串列效率高???
陣列和連結串列在增刪查改方面誰的效率高呢, 這個問題相信很多人都遇到過,但更多的人只是記住兩句口訣:陣列查改方便,連結串列增刪效率高。
無論是書本,老師,還是許多的前輩都告訴我們,這是對的。理由如下:
在查改方面陣列可以通過索引迅速確定位置,而連結串列只能依次尋找,所以陣列有著無法匹敵的優勢。而在增刪方面,陣列每次插入元素都要將該元素後面的所有元素向後挪動一位,刪除則將該元素之後所有元素向前移動一位。而連結串列在插入元素的時候,只需將該元素前驅的指標指向本身,將本身的指標指向後驅,刪除則將該元素的前驅指向該元素的後驅。相比之下,連結串列確實優勢挺大。
首先,筆者想說,上面的理由全是對的,但是忽略了一個很嚴重的問題。那就是增刪其實不僅僅是增刪,它還包括查,增刪的過程如下:
增:找到插入該元素的位置,插入該元素
刪:找到刪除該元素的位置,刪除該元素
既然增刪包括了查,而在查這一方面,陣列效率比連結串列高,又怎麼能肯定地說連結串列增刪效率比陣列高呢,所以這個結果還有待爭議,筆者為此特地做了個實驗(這裡只列出插入的實驗,刪除的也同理):
import java.util.ArrayList; import java.util.LinkedList; public class LinkedAndArray { /* * 比較陣列和連結串列執行插入資料時花費的時間 * len 定義陣列的長度 * num 迴圈插入的次數(插入一次時間太短難比較) * index 每次插入的位置 */ public static void printTime(int len,int num,int index){ LinkedList<Integer> link=new LinkedList<Integer>();//定義連結串列 ArrayList<Integer> arr=new ArrayList<Integer>();//定義陣列 //為陣列賦初值 for (int i = 0; i < len; i++) { arr.add(i); link.add(i); } //計算陣列執行操作花費的時間 long startTime=System.currentTimeMillis(); for (int i = 0; i < num; i++) { arr.add(index,2); } long endTime=System.currentTimeMillis(); System.out.println("陣列花費時間:"+(endTime-startTime)+"毫秒"); //計算連結串列執行相同操作花費的時間 long sTime=System.currentTimeMillis(); for (int i = 0; i < num; i++) { link.add(index,2); } long eTime=System.currentTimeMillis(); System.out.println("連結串列花費時間:"+(eTime-sTime)+"毫秒"); } public static void main(String[] args) { printTime(10000,5000,1000); } }
最後輸出結果是:好多人一看,誒,對啊,跟我們往常的結論是一樣的。別急,下面還有。當我們把插入的位置更改為陣列的一半,也就是5000時,輸出結果如下:
當我們將陣列長度變大時,這個差異更加明顯:
按照上面的這個資料可以粗略的計算出:連結串列每查詢一個位置花費時間為0.000006毫秒(五個0),陣列每移動一個位置花費時間為:0.00000088毫秒(六個0),以上計算是在忽略連結串列插入過程和忽略陣列查詢過程的情況下進行的。
經過筆者反覆試驗,可以得出一個結論:在靠前的位置插入資料,連結串列效率較高,在靠後位置插入資料,陣列效率較高
那哪裡是靠前,哪裡是靠後呢,筆者又反覆試驗了好多次,然後有了如下結論:比如有一個長度都為n的陣列、連結串列,當n長度小於一萬時,有略高於0.2n的位置是屬於靠前的,當n的長度越大,達到百萬級別時,只有大概0.1n的長度算是靠前的了。
所以綜合來說,在增刪方面的效率比較上,陣列有八九成勝算,而連結串列只有一到兩成。