簡體   English   中英

將N個元素插入到列表中的復雜性順序是什么 <T> 如果我不指定容量?

[英]What is the order of complexity of inserting N elements into a List<T> if I don't specify a capacity?

假設我有類似的東西

List<int>() numbers = new List<int>();
int num;
while(int.TryParse(Console.ReadLine(), out num))
{
    numbers.Add(num);
}

假設添加的元素數為N 考慮到插入通常是O(1)而是O(n)的事實,我想知道總復雜度是描述為O(N)還是O(N^2) 。一會兒”內部需要將列表復制到更大的數組中。

.net使用一種算法的變體,當列表已滿時,該數組將分配一個兩倍大的數組,將現有元素復制到其中,並釋放舊元素,從而基本上擴展了初始數組。

實際上,所有提供列表等效項的語言都可能這樣做,因為沒有理由不這樣做。

並假設添加的元素數為N。我想知道當考慮到插入通常是O(1)時,總復雜度是O(N)還是O(N ^ 2)。 ),但當內部需要將列表復制到更大的數組中時,將“偶爾”顯示O(n)。

這是用於插入n元素的攤銷O(n) ,是用於插入一個元素的攤銷O(1)

基本上,攤銷意味着插入n元素的操作總數平均為O(n) ,即使由於插入必須擴展數組,一次插入操作可能比另一次執行更多的操作。

要看到這一點,請考慮我在第一段中描述的經典算法。 假設我們的容量最初為1。我們將計算擴展數組時執行的操作數。 插入第一個元素時,我們有:

0

操作,因為數組未擴展。

插入第二個元素必須將現有元素復制到新數組,然后才執行插入。 為了清楚起見,我們將忽略內存操作引入的常量。 因此,這是:

1

操作(復制1個元素,新容量為2)。

當插入第三個元素時,我們有:

2 

操作(復制2個元素,新容量為4)

插入第四個元素時,我們有0操作,因為我們還有剩余空間。

當插入第五個時,我們有:

4

操作(復制4個元素,新容量為8)。

通常,當插入第2^k+1個元素時,我們將具有:

2^k 

操作。

k可以是多少? log base 2 of nlog n ),因為這樣我們將有足夠的空間容納n元素。

因此,所有調整大小操作的復雜度由總和給出:

S = 1 + 2 + 4 + ... + 2^k, k = log n
S = (1 - 2^k) / (1 - 2) // sum of a geometric progression with ratio 2
  = 2^k - 1
  = 2^(log n) - 1
  = n - 1
  = O(n)

因此總復雜度為O(n)加上另一個O(n)因為我們沒有計算實際的插入數。 但這仍然是O(n)

這完全取決於在此框架實例上運行的List實例將如何增長。 我無法預料的是,答案可能會因操作系統資源,框架版本和列表的完整程度而有所不同。 這是一個實現細節。

顯然,提供能力會提高性能。 如果您不確定確切的數目,則可以設置多余的容量,然后在全部添加之后使用TrimExcess() 容量只是為了避免必須增加列表的開銷。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM