2016-05-26 26 views
7

Ho scoperto che ci sono molte controversie sulla complessità asintotica di List.Add(). Sospetto che sia la causa peggiore dello scenario that causes underlying array to resize e logicamente sarebbe l'operazione O(n). Tuttavia, lo array grows twice in size ogni elenco di tempo esaurisce lo spazio. Ciò rende la proporzione necessaria per gli elementi n proporzionale a log(n).Qual è la complessità asintotica di List.Add?

Ciò non significa che la complessità asintotica dell'operazione Add nel caso medio sarà O(n/log(n))?

Il vero parametro di riferimento per List.Add() è il seguente. Tuttavia, i benchmark non sono realmente espressivi per tale operazione - potremmo essere a corto di memoria prima che qualsiasi deviazione dalla linea retta (in scala logaritmica) diventi visibile.

benchmark

+0

Quando la matrice aumenta, gli elementi N/2 esistenti vengono spostati. Ecco perché pensi che sia il registro N. Ma la crescita della capacità, nuova ma inusitata, in modo esponenziale. Ciò neutralizza l'effetto. Il primo elemento viene spostato nel registro N volte. Gli ultimi elementi N/2 vengono spostati 0 o 1 volte. – usr

risposta

9

Ciò significa che la amortized complexity di List.Add() può essere calcolato sommando le operazioni di ridimensionamento e quindi moltiplicando per numero totale aggiunte apportate all'elenco.

T(n) = (2 + 4 + 8 + ... + n/2 + n)/n 

ma nota che la somma è un geometric series, e possiamo fare meglio di supponendo che è (sommatoria) n*log(n):

T(n) < 2n/n = 2 -> T(n) is in O(1) 

Nota: Qui io parto dal presupposto che dire add() come aggiungendo . L'inserimento di un elemento in una posizione arbitraria richiede tempo O(n) e sarà necessario tenere conto anche di quello, che modificherà il risultato finale dalla complessità ammortizzata O(1) alla complessità ammortizzata O(n).

+0

Ottimo lavoro che spiega anche la complessità ammortizzata –

+0

In modo che per aggiungere l'elenco di n elementi si spostino 2n elementi, giusto? –