關於Array和List的區別(轉載)

Array、List的區別

Array—是基於索引(index)的數據結構,它使用索引在數組中搜索和讀取數據是很快的。Array獲取數據的時間複雜度是O(1),但是要刪除數據卻是開銷很大的,因爲這需要重排數組中的所有數據。

List—是一個有序的集合,可以包含重複的元素,提供了按索引訪問的方式,它繼承Collection。

Array和List都屬於順序表。

Array是一段連續的存儲結構

int[] i=new int[3]

i  其實記錄的是數組的首地址,而i[1]其實相當於在i的地址的基礎上加上1個整數的地址偏移,然後再取這塊地址中的值。

List則是不連續的存儲結構, List的每個節點都有着一個Next屬性,這個屬性則記錄着他的下一個節點的地址。

也就是說當我們想找第100個節點的時候,他還是需要從第一個節點,然後做99次Next操作,才能找到list[99]節點。

在查找一個元素時時分別生成以下IL碼

Array:

  IL_0020:  ldloc.0

  IL_0021:  ldc.i4.3

  IL_0022:  ldelem.i4

  IL_0023:  stloc.2

List:

  IL_0022:  ldloc.0

  IL_0023:  ldc.i4.3

  IL_0024:  callvirt   instance !0 class [mscorlib]System.Collections.Generic.List`1<int32>::get_Item(int32)

  IL_0029:  stloc.2

通過這兩段IL,我只是希望證明List和Array對索引元素的方式是不同的。當然,我們無從知道Microsoft對List方法get_Item的實現。但是我們不難想象:
因爲List是一個鏈表,所以我需要從第一個元素開始逐個Next到所需索引的元素。這是一個耗時的過程。

 1. 從空間擴展角度上來說:


  數組必須要在初始化時分配固定的大小,比如說int[] a=new int[3];如果我們僅僅寫int[] a=new int[];編譯器就會無情地給我們報錯。但是List由於空間不必連續,所以無須指定初始大小。

  總結1: 當不確定大小時,最好使用List 代替Array。

 2. 從操作角度上來看:

  關於索引這個就不贅述了。

  總結2:當需要大量的查找操作時,最好使用Array。

  對於插入(刪除)操作,很多人是從插入(刪除)的時間上分析,說List優於Array,我覺得是不合理的。

  更合理的解釋應該是從兩個角度分析(以插入爲例):

  <1> 指定位置插入指定元素:

  對於Array講,有兩套解決方案:

  A. 使用一個新數組,N+1個元素重新賦值的過程。一個for循環,時間複雜度O(n)。

  B. 在原數組上操作,那麼首先需要爲該數組預留空間,這是個很難辦的事情。而且其後續元素的移動耗費時間複雜度仍未O(n)。

  對於List來講,很多人說複雜度就是O(1)。這其實是不合理的,因爲List插入元素固然容易,但是在指定位置的插入,需要一個時間複雜度爲O(n)的查找過程。

  但是隻考慮時間複雜度是不夠的,我們要考慮總體的情況。如果使用新數組,不僅浪費了新的空間,而且需要反覆的賦值過程,是N+1次。如果不使用新數組,預留空間實在太麻煩,因此綜上所述,還是List好。

  <2> 給出前一個節點,然後在後面插入元素。這個我的意思就是不僅僅給出了PreviousNode的Value,還給出了他的Next。這個情況我就不廢話了,List的優勢太大了。可是在實際情況中,這種情況的可能性幾乎爲零。

  因此,總結3:當需要進行頻繁的插入,刪除操作時,最好使用List代替Array。

  另外,給出個不太重要的補充,由於List需要存儲他下一個節點的地址,所以List 比Array相對起來浪費了更多的空間

 

      也就是說雖然使用list<T>強類型範性,能夠節約裝箱拆箱時間,但查詢速度會有很多問題。

在實際使用中,對變化不大,查詢次數頻繁的,我們應該考慮list<T>外的情況

當然,就查詢某個值的速度而言,還是 Hashtable  或 Dictionary  最快,當然這兩者和我們在討論的東西,結構完全不相同,沒有可比性。畢竟數組,是節約空間,而hash表是散列的,犧牲空間來換取速度


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章