if n was a 1,000,000
then
(n^2 + n) / 2 = 500000500000 (5.00001E+11)
(n^2) / 2 = 500000000000 (5E+11)
(n^2) = 1000000000000 (1E+12)
1000000000000.00 cosa?
Mentre la complessità ci offre un modo per prevedere un costo reale (secondi o byte a seconda che stiamo parlando di complessità temporale o complessità spaziale), non ci fornisce un numero di secondi, o qualsiasi altro particolare unità.
Ci dà un certo grado di proporzione.
Se un algoritmo deve fare qualcosa di n² volte, allora ci vorrà n² × c per un certo valore di c che è il tempo impiegato da ogni iterazione.
Se un algoritmo deve fare qualcosa di n² ÷ 2 volte, allora ci vorrà n² × c per un valore di c che è il doppio di ogni iterazione.
In entrambi i casi, il tempo impiegato è ancora proporzionale a n².
Ora, questi fattori costanti non sono qualcosa che possiamo semplicemente ignorare; in effetti si può avere il caso in cui un algoritmo con complessità O (n²) fa meglio di uno con O (n) complessità, perché se stiamo lavorando su un piccolo numero di elementi l'impatto dei fattori di consenso è maggiore e può sopraffare altre preoccupazioni . (Infatti, anche O (n!) È uguale a O (1) per valori sufficientemente bassi di n).
Ma non sono ciò di cui la complessità ci parla.
In pratica, ci sono alcuni modi in cui possiamo migliorare le prestazioni di un algoritmo:
- Migliora l'efficienza di ogni iterazione: O (n²) gira ancora in n² × c secondi, ma c è più piccolo.
- Riduci il numero di casi visti: O (n²) continua a essere eseguito in n² × c secondi, ma n è minore.
- Sostituisci l'algoritmo con uno che ha gli stessi risultati, ma una complessità inferiore: es. se potessimo ripubblicare qualcosa O (n²) a qualcosa O (n log n) e quindi cambiare da n² × c₀ secondi a (n log n) × c₁ secondi.
O per guardarlo in un altro modo, abbiamo ottenuto f(n)×c
secondi e puoi migliorare le prestazioni riducendo c
, riducendo n
o riducendo quale f
restituisce per un dato n
.
Il primo che possiamo fare con alcuni micro-opts all'interno di un loop, o usando un hardware migliore. Dà sempre un miglioramento.
Il secondo che possiamo fare, forse, identificando un caso in cui possiamo eseguire un cortocircuito dall'algoritmo prima che tutto venga esaminato, o filtrare alcuni dati che non saranno significativi. Non darà un miglioramento se il costo di ciò è superiore al guadagno, ma in generale sarà un miglioramento maggiore rispetto al primo caso, specialmente con un grande n.
Il terzo che possiamo fare utilizzando completamente un algoritmo diverso. Un classico esempio potrebbe sostituire un bubble sort con un quicksort. Con un basso numero di elementi potremmo aver peggiorato le cose (se c₁ è maggiore di c₀), ma generalmente consente i maggiori guadagni, specialmente con molto grandi n.
Nell'uso pratico, le misure di complessità ci permettono di ragionare sulle differenze tra algoritmi proprio perché ignorano la questione di come la riduzione di n o c aiuterà, a concentrarsi sull'esame di f()