數組是壹種連續的存儲結構。
int【】I = new int【3】
I實際上記錄了數組的第壹個地址,I【1】實際上相當於在I的地址上加上1個整數的地址偏移量,然後取這個地址中的值。
List是壹個不連續的存儲結構,List的每個節點都有壹個Next屬性,記錄下壹個節點的地址。
也就是說,當我們要找到第100個節點時,他仍然需要從第壹個
數組是壹種連續的存儲結構。
int【】I = new int【3】
I實際上記錄了數組的第壹個地址,I【1】實際上相當於在I的地址上加上1個整數的地址偏移量,然後取這個地址中的值。
List是壹個不連續的存儲結構,List的每個節點都有壹個Next屬性,記錄下壹個節點的地址。
也就是說,當我們要找到第100個節點時,他仍然需要從第壹個節點開始做99次下壹步操作才能找到list【99】節點。
搜索元素時,將分別生成以下IL代碼。
數組:
IL_0020: ldloc.0
IL_0021: ldc.i4.3
IL_0022: ldelem.i4
IL_0023: stloc.2
列表:
IL_0022: ldloc.0
IL_0023: ldc.i4.3
IL_0024: callvirt實例!0類【mscorlib】系統。collections . generic . list ` 1 & lt;int32》* get _ Item(int 32)
IL_0029: stloc.2
通過這兩段IL,我只想證明List和Array對元素的索引方式是不同的。當然,我們不知道微軟對列表方法get_Item的實現。但不難想象:
因為List是壹個鏈表,所以我接下來將從第壹個元素開始,逐個查找所需索引的元素。這是壹個耗時的過程。
1.從空間擴展的角度來看:
數組在初始化時必須分配壹個固定的大小,例如int【】a = new int【3】;如果我們只寫int【】a = new int【】;編譯器會毫不留情地給我們壹個錯誤。然而,列表不需要指定初始大小,因為空間不必是連續的。
總結1:當大小不確定時,最好使用List而不是Array。
2.從操作角度來看:
我不會詳細介紹該指數。
總結2:當需要大量查找操作時,最好使用數組。
對於插入(刪除)操作,很多人從插入(刪除)的時候開始分析,說List優於Array,我認為這是不合理的。
更合理的解釋應該從兩個角度來分析(以插入為例):
& lt1》在指定位置插入指定元素:
對於陣列,有兩種解決方案:
A.使用新數組,N+1個元素被重新分配。時間復雜度為O(n)的for循環。
B.要對原始陣列進行操作,首先為陣列預留空間非常困難。此外,其後續元素移動的耗時復雜度仍然不是O(n)。
對於List,很多人說復雜度是O(1)。這實際上是不合理的,因為向列表中插入元素很容易,但在指定位置的插入需要時間復雜度為O(n)的搜索過程。
但是僅僅考慮時間復雜度是不夠的,我們應該考慮全局。如果使用新的數組,不僅會浪費新的空間,還需要重復的賦值過程,這是N+1次。如果不使用新數組,預留空間就太麻煩了,所以綜上所述,List更好。
& lt2 & gt給出前壹個節點,然後在它後面插入元素。我的意思是不僅給出了前壹個節點的值,而且給出了下壹個節點的值。這種情況我就不廢話了,單子的優勢太大了。但在實際操作中,出現這種情況的可能性幾乎為零。
因此,總結3:當需要頻繁的插入和刪除操作時,最好使用列表而不是數組。
此外,給出壹個不太重要的補充。因為List需要存儲其下壹個節點的地址,所以List比Array浪費更多的空間。
也就是說,盡管列表
在實際使用中,我們應該考慮list《T》外部形勢
當然,就查詢某個值的速度而言,Hashtable或Dictionary是最快的。當然,這兩者與我們正在討論的內容完全不同,沒有可比性。畢竟,數組節省空間,而哈希表是散列的,為了速度而犧牲空間。