Analisi ammortizzata? (Peggiori garanzie prestazionali)


13

Che cos'è l'analisi ammortizzata? E come può aiutarmi a ottenere garanzie di prestazioni nel caso peggiore nei miei programmi?

Stavo leggendo che le seguenti tecniche possono aiutare il programmatore a ottenere garanzie di prestazioni nel peggiore dei casi (vale a dire con parole mie: garantire che il tempo di esecuzione di un programma non superi il tempo di esecuzione nel cast peggiore):

  • Algoritmi randomizzati (ad es. L'algoritmo quicksort è quadratico nel peggiore dei casi, ma ordinare casualmente l'input offre una garanzia probabilistica che il suo tempo di esecuzione è linearitmico)
  • Sequenze di operazioni (la nostra analisi deve tener conto sia dei dati sia della sequenza di operazioni eseguite dal cliente)
  • Analisi ammortizzata (un altro modo per fornire una garanzia di prestazione è di ammortizzare il costo, tenendo traccia del costo totale di tutte le operazioni, diviso per il numero di operazioni. In questa impostazione, possiamo consentire alcune operazioni costose, pur mantenendo il costo medio di operazioni basse. In altre parole, dividiamo il costo delle poche operazioni costose, assegnandone una parte a ciascuna di un gran numero di operazioni economiche)

L'autore ha menzionato l'uso del ridimensionamento della struttura dei dati dell'array per Stack come esempio di come ottenere un'analisi ammortizzata, ma ancora non capisco cosa sia l'analisi ammortizzata e come possa essere effettivamente implementata (struttura dei dati? Algoritmo?) Per ottenere risultati peggiori -cast garanzie di prestazione

Risposte:


14

Non implementare analisi ammortizzate. È una tecnica per ottenere Olimiti più precisi .

L'osservazione essenziale che devi fare è che operazioni costose non possono avvenire in nessun momento.

Nel caso di una struttura dati supportata da array, l'array deve essere ridimensionato di tanto in tanto, quando è pieno. Questa è l'operazione più costosa e richiede O(n)tempo. Tutti gli altri inserti nell'array sono O(1).

Per determinare il runtime per l'inserimento di nelementi, è possibile moltiplicare nper l'operazione più costosa O(n), il che si traduce in un comportamento di runtime complessivo di O(n^2).

Tuttavia, ciò non è preciso perché il ridimensionamento non può avvenire molto spesso.

Quando si parla di denaro, si ammortizza il costo, quando si paga il debito con più piccoli pagamenti nel tempo.

Possiamo usare questo modello anche per pensare agli algoritmi. Sostituiamo semplicemente "tempo" con "denaro" per evitare la mappatura mentale.

Una volta che l'array è pieno alla sua lunghezza n, possiamo raddoppiarne le dimensioni. Dobbiamo effettuare le seguenti operazioni:

  • Allocare 2nblocchi di memoria
  • copia narticoli

Se supponiamo che sia l'allocazione della memoria sia la copia avvengano in tempo lineare, questa sarà un'operazione molto costosa. Tuttavia, ora possiamo usare l'idea del debito e ammortizzarla per la nostra analisi. Solo, ammortizzeremo il nostro debito prima di farlo effettivamente.
Supponiamo che il nostro saldo (di denaro / tempo) sia tornato a 0 (ovvero non abbiamo debiti né avanzi) una volta ridimensionato l'array.

Ciò ha le seguenti implicazioni:

  • L'inserimento degli narticoli successivi coprirà i costi di ridimensionamento e copia (abbiamo nusato slot e slot nnon utilizzati`)

Ora possiamo pensare a quanto deve pagare ogni operazione di inserimento:

  • L'inserto
  • Il costo di allocare un pezzo di memoria
  • il costo per spostarlo nella memoria appena allocata

Ora abbiamo coperto i costi per allocare memoria, copiare e inserire gli nelementi successivi . Tuttavia, abbiamo ancora trascurato l'allocazione dello spazio per i vecchi nelementi e la loro copia.

Distribuiamo semplicemente i costi dei nostri vecchi nelementi ai nostri nuovi (ancora da inserire) nelementi:

  • Il costo di allocare un pezzo di memoria
  • il costo per spostarlo nella memoria appena allocata

In totale, ogni operazione di inserimento avrà un costo di 5 unità. Questo paga per il suo proprio inserimento, lo spostamento e l'allocazione dello spazio per se stesso e uno dei vecchi elementi.

Ogni operazione di inserimento richiede ancora una quantità costante di tempo, ma il ridimensionamento avviene gratuitamente: lo abbiamo ammortizzato spendendo "più" tempo su ogni inserimento.

Di conseguenza, l'inserimento di nelementi richiede O(n)tempo.

Altre tecniche per l'analisi ammortizzata sono spiegate qui .


1

Prima di tutto: è una tecnica per analizzare i tempi di esecuzione del programma, non una tecnica di implementazione per algoritmi.

L'esempio citato nell'elenco è positivo: aggiungere un singolo elemento alla struttura dati supportata da array. Per ogni singola operazione di aggiunta, il caso peggiore è quello di copiare tutti gli elementi esistenti. Questo tipo di analisi è troppo pessimista, in quanto non è necessario farlo se si utilizza una strategia di ridimensionamento sana (moltiplicando la dimensione per alcuni x> 1,0). L'analisi dice quindi che hai un limite O (n ^ 2) - O (n) per elemento per volta n elementi - mentre il tempo di esecuzione effettivo è solo O (n).

Se si calcola la media del costo di ridimensionamento su tutti gli elementi inseriti (la maggior parte dei quali non necessita di ridimensionamento) si sta effettuando un'analisi ammortizzata. L'analisi ammortizzata si traduce in un limite O (n) che corrisponde al comportamento effettivo dell'algoritmo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.