2010-01-12 11 views
10

Vedo il vantaggio dell'utilizzo di due stack se si utilizza un'implementazione dell'array dato che gli stack vengono implementati più facilmente utilizzando gli array rispetto alle code. Ma se si usano elenchi concatenati, qual è il vantaggio? L'azione di far scoppiare lo stack sulla coda aumenta l'overhead per entrambe le implementazioni di elenchi collegati e array.Perché utilizzare due stack per fare una coda?

+0

Chi usa due stack per fare una coda? Non capisco davvero la situazione (sorry :( – helios

risposta

16

E 'un modo comune per implementare una coda in linguaggi di programmazione funzionale con puramente funzionale (immutabile, ma la condivisione di struttura) liste (ad esempio Clojure, Haskell, Erlang ...):

  • usare un paio di liste per rappresentare una coda in cui elementi sono in ordine FIFO nella prima lista e in ordine LIFO nel secondo elenco
  • Enqueue alla coda anteponendo al secondo elenco
  • dequeue dalla coda prendendo il primo elemento del primo lista
  • se il primo lista è vuota: invertire la seconda lista e sostituire la prima lista con esso, e sostituire il secondo elenco con un elenco vuoto

(tutte le operazioni restituiscono il nuovo oggetto coda in aggiunta ad eventuali valori restituiti)

Il punto è che l'aggiunta (rimozione) di un elemento a (da) il fronte di una lista puramente funzionale è O (1) e l'operazione inversa che è O (n) è ammortizzata su tutti i dequeues, quindi è vicino a O (1), fornendo così un'implementazione della coda ~ O (1) con strutture dati immutabili.

+0

il secondo passo, credo che l'ultima parola dovrebbe essere 'list' piuttosto che' queue' per renderla come 'enqueue alla coda prepending al secondo elenco'. –

+0

Grazie @LihangLi, corretto! – liwp

-2

È una buona esperienza di apprendimento, ma non pratica.

3

È possibile effettuare una coda immutabile utilizzando due pile immutabili.

Ma, se si desidera solo una coda mutabile, l'uso di due stack è un ottimo modo per renderlo più lento e complicato rispetto all'utilizzo di un elenco collegato.

5

Questo approccio può essere utilizzato per creare una coda lock-free utilizzando due stack atomici a elenco singolo collegati, come fornito da Win32: Interlocked Singly Linked Lists. L'algoritmo potrebbe essere come descritto in liwp's answer, sebbene il passo di reimballaggio (punto 4) possa essere ottimizzato un po '.

Strutture e algoritmi di dati privi di blocchi è una zona di programmazione molto interessante (per alcuni di noi), ma devono essere utilizzati con molta attenzione. In una situazione generale, gli algoritmi basati su lock sono più efficienti.

+0

In un caso di lettore singolo multi-scrittore, è facile gestire le operazioni di "accodamento" in modo efficiente senza blocco e allo stesso modo per dequeue (non dover bloccare i writer e assumere un singolo lettore) se si avvia la dequeue con un'operazione "pop all" nella posta in arrivo (in pratica un 'Interlocked.Exchange'). Se ci potrebbero essere più lettori, è probabilmente meglio lasciarli usare il locking per arbitrare tra loro (il loro blocco non sarebbe t influenzano gli scrittori) – supercat

+0

Questa è la spiegazione per cui sono venuto qui alla ricerca di un buon signore signore. –