È possibile implementare tre stack in un array, con O (1) push / pop time?


9

Due stack possono essere implementati in modo efficiente utilizzando un array di dimensioni fisse: lo stack n. 1 inizia dall'estremità sinistra e cresce verso destra, mentre lo stack n. 2 inizia dall'estremità destra e cresce verso sinistra. Lo stesso è possibile per tre pile?

Più in particolare, è possibile implementare tre stack date le seguenti condizioni:

  1. Hai un array di dimensioni fisse che può contenere N oggetti.
  2. Finché la somma delle tre dimensioni dello stack è <N, push () non dovrebbe fallire.
  3. Entrambe le operazioni push () e pop () dovrebbero richiedere O (1).
  4. Oltre all'array, è possibile utilizzare solo O (1) spazio aggiuntivo.

Ecco alcuni esempi di soluzioni che non soddisfano questi requisiti:

  • Dividere l'array in 3 parti fisse e utilizzare ciascuna parte per una pila (viola 2).
  • Simile al precedente ma con confini mobili tra pile (viola 3).
  • Semplici implementazioni basate su liste collegate (viola 4).

Accetterò algoritmi non banali o prove di impossibilità anche se non soddisfano tutte le condizioni (1) - (4) esattamente, ad esempio, un algoritmo in cui push / pop prende O (1) tempo ammortizzato, o dove il la memoria aggiuntiva è più piccola di O (N), ad es. O (registro N). O una prova di impossibilità che dimostra che, ad esempio, è impossibile accedere a meno di 5 elementi dell'array per push / pop.


1
Non so se lo consideri una violazione del requisito 4, ma se ogni "oggetto" nell'array N oggetti può includere un campo aggiuntivo come un indice intero, puoi implementare gli "elenchi collegati" all'interno dell'array . Puoi tenere l'indice della parte superiore di ciascuna delle 3 pile usando 3 variabili esterne e ogni "oggetto" può puntare all'elemento precedente nella sua pila.
Avi Tal

Per "oggetti" intendevo cose che push () accetta e pop () restituisce. Dal punto di vista dell'implementazione dello stack, sono solo blocchi di dati opachi (ad esempio, un oggetto potrebbe essere un numero intero a 32 bit). L'implementazione dello stack non dovrebbe modificare questi oggetti in alcun modo.
user1020406

1
N

O(N)

O(N)

Risposte:


6

Θ(nε)Θ(n) nn


0

Sia N la lunghezza dell'array sottostante. Posso immaginare gli stack come elenchi collegati di blocchi di grandi dimensioni, in modo che il numero complessivo di blocchi non sia superiore a O (log2 (N)). Posiziona il terzo stack tra i primi due, all'indice di N / 2. Quindi abbiamo 3 aree occupate e 2 gratuite. Quando una pila non può accettare l'elemento successivo, significa che un'area libera è esaurita. Se anche l'altro è esaurito, allora l'intera memoria è esaurita. Altrimenti, esiste un'altra area libera con dimensioni non superiori a N / 2. Continua la pila traboccante in quell'area libera. in modo che l'intera configurazione assomigli al layout iniziale degli stack. Poiché la memoria libera ora non è più della metà dell'iniziale, non ci sarà più del log2 (N) di tali operazioni di collegamento. Ogni operazione di collegamento richiede una quantità fissa di memoria per salvare lo stato precedente dello stack. Così,


1
Come si ricicla la memoria ottenuta facendo scoppiare le cose da uno dei grossi pezzi?
Emil Jeřábek,

Buona domanda. La risposta rapida è quella parte che diventa libera restituisce la sua memoria all'area libera da cui era stata precedentemente prelevata. Ma cosa succede se l'area libera si restringe dal momento della memoria di allocazione per quel blocco, e il blocco ora non è adiacente ad esso? Questo porta alla frammentazione della memoria libera, ci possono essere più di 2 aree libere, che rovinano tutta la mia costruzione.
Alexei Kaigorodov,

Qui il problema è sicuramente il problema, ma la costruzione di Alexei fornisce un bel limite superiore per la versione del problema di cui Dmitri ha chiesto nei commenti: cosa succederebbe se avessimo bisogno che tutte le spinte accadessero prima che tutti i pop? Mi chiedo se in questo caso sia possibile qualcosa di meglio di O (log N).
user1020406
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.