Ordinamento utilizzando stack di sola lettura


14

Considera la seguente impostazione:

  • ci viene data una pila che contiene elementi.Sn
  • possiamo usare un numero costante di pile extra.O(1)
  • possiamo applicare le seguenti operazioni su questi stack:
    1. controlla se uno stack è vuoto,
    2. confronta i primi oggetti di due pile,
    3. elimina l'elemento in cima a una pila,
    4. stampa l'articolo in cima a una pila,
    5. copia l'elemento in cima a una pila in un'altra pila,
    6. copia il contenuto di una pila in un'altra pila.

Si noti che queste sono le uniche operazioni consentite. Non siamo in grado di scambiare oggetti e non ci è permesso di inserire alcun oggetto in nessuna delle pile ad eccezione della copia dell'articolo in cima a una pila (dopodiché il contenuto precedente della pila di destinazione viene scartato e conterrà solo l'oggetto copiato) .

Ecco un algoritmo per ordinare le pile con confronti :O(n2)

last := empty
for i from 1 to n
  min := empty
  w := s
  while w is not empty
    if w.top > last and w.top < min
      min := w.top
    delete w.top
  print min
  last := min

Possiamo fare di meglio?

Esiste un programma che stampa l'elenco ordinato degli elementi negli stack utilizzando solo confronti ?O(nlogn)


2
Sembra che i registri si comportino come pile? Sembra che tu stia parlando di operazioni push e pop. Sono le tue domande? Come ordinereste uno stack usando più stack e operazioni dello stack?
AturSams,

2
Con registri puoi: basta inserire ogni numero in un registro ( O ( n ) ) e quindi applicare un normale algoritmo di ordinamento ( O ( n lg n ) ). nO(n)O(nlgn)
Kaveh,

1
Vuoi usare i registri ? Altrimenti il ​​problema banalizza, come commentato da Kaveh. O(1)
Yuval Filmus,

1
Prego. Pensavo che ci fosse dato un numero di stack, non solo uno, lo aggiusterò.
Kaveh,

2
@akappa, sei sicuro che possa essere usato in questo modo di vedere? Non possiamo mantenere arbitrariamente perse dimensioni superiori a 1. Non è necessario archiviare i blocchi ordinati?
Kaveh,

Risposte:


1

Penso di poter ora dimostrare un limite inferiore non banale. L'idea è quella di implementare tali programmi con una famiglia di programmi di ramificazione comparativa. Il presupposto di "sola lettura" significa che la nostra famiglia di programmi di ramificazione utilizza poco, ovvero spazio ) . Quindi applichiamo il limite inferiore S T = Ω ( n 2 ) dimostrato da Borodin et al. in "Un compromesso spazio-tempo per l'ordinamento su macchine non ignare". Questo ci dà un n 2 / log n limite inferiore per il tempo.O(logn)ST=Ω(n2)n2/logn

Più in dettaglio: possiamo rinunciare all'operazione 5 sopra. In parole povere, se possiamo già confrontare le intestazioni di due liste e stampare la testa di una lista, non è necessario isolare la testa di una lista su un particolare registro. Supponendo ciò, vediamo che ogni registro nella macchina memorizza solo una sottostringa finale dell'input.

Supponiamo che il nostro programma di registro abbia righe di codice e registri k , X 1 , ... , X k .KX1,...,XK

Fix . Costruiamo il programma di ramificazione comparativa per stringhe di lunghezza n come segue. Crea un nodo per ogni tupla ( i , d 1 , , d k ) dove 1 i e 0 d 1 , , d kn . L'idea è che i calcoli nella macchina del registro corrispondono ai percorsi nel programma di diramazione e siamo al nodo ( i , d 1 , ... , dnn(io,d1,...,dK)1i0d1,,dkn se siamo alla riga i nella macchina del registro e la lunghezza della stringa memorizzata in X i è d i . Ora, dobbiamo definire i bordi diretti del programma di ramificazione(i,d1,,dk)iXidi

Se la riga è del moduloi

se poi goto i 1 altro goto i 2Xu<Xvi1i2

quindi per tutto , il nodo ( i , d 1 , ... , d k ) viene etichettato confrontando l' elemento d u -th e d v -th dell'input e facendo in modo che il bordo "vero" vada a ( i 1 , d 1 , ...d1,,dk(i,d1,,dk)dudv e il bordo "falso" su ( i 2 , d 1 , ... , d k(i1,d1,,dk) .(i2,d1,,dk)

Se la riga è del moduloi

, vai alla linea i X1tail(X2)i

poi c'è una freccia da qualsiasi nodo a ( i , d 2 - 1 , ... , d k ) .(i,d1,,dk)(i,d21,,dk)

Se la riga è del moduloi

, vai alla riga i print(head(Xu))i

poi c'è una freccia da qualsiasi nodo a ( i , d 1 , ... , d k ) che è etichettata dal nodo d u dell'ingresso.(i,d1,,dk)(i,d1,,dk)du

Spero che questi esempi chiariscano come intendo costruire il mio programma di diramazione. Quando tutto è detto e fatto, questo programma di ramificazione ha al massimo nodi, quindi, dispone di spazi O ( log n )nkO(logn)


0

Sei in grado di contare gli elementi? Quindi, penso, ci sia un'implementazione Mergesort abbastanza semplice. Se fossi in grado di mettere simboli aggiuntivi in ​​pila, potresti risolverlo con 3 pile in questo modo:

Se abbiamo un solo elemento, l'elenco è già ordinato. Ora supponiamo che abbiamo già ordinato la metà superiore dello stack. Possiamo copiare la metà superiore (in ordine inverso) nella seconda pila e posizionare sopra di essa un simbolo di separazione. Ora abbiamo di nuovo 3 pile (poiché possiamo ignorare i simboli già ordinati sotto il simbolo di separazione) e possiamo ordinare la metà inferiore. Finalmente possiamo copiare la metà inferiore ordinata in una terza pila in ordine inverso e unire entrambe le metà nella pila originale.

Tutte le operazioni costano tempo lineare, pertanto abbiamo ordinato l'elenco in O(nlogn)

(Si noti che abbiamo bisogno di pile di dimensioni causa dei simboli di separazione, ma questo può essere facilmente corretto usando un altro stack)nlogn


Dato che non puoi mettere nuovi elementi in pila, potresti avere problemi nei punti di separazione. Per risolvere questo problema puoi fare quanto segue con alcune pile aggiuntive:

Copia la parte superiore n2logn

Infine ripetere la procedura con gli elementi aggiuntivi al massimo volte e li fondono alla pila originale in tempo lineare. Ordinamento dei costi pile, per qualche costante c , al massimo c n loglognccnlogn+cn2logn2+cn4logn4+ ...=O(nlogn)O(nlogn)


Non sono sicuro di capire. Come possiamo, ad esempio, copiare la metà superiore della pila in ordine inverso su un'altra pila quando non possiamo mai spingere alcun elemento su una pila?
Siddharth,

Non possiamo spingere alcun nuovo elemento in una pila, ma secondo 5 siamo in grado di spingere l'elemento superiore di una pila in un'altra. Quindi copiare la pila in ordine inverso richiede al massimo tempo lineare. Quindi suppongo che non fosse quello che stavi chiedendo?
cero,

Non puoi spingere nulla sopra altri elementi come spiegato nella domanda.
Kaveh,
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.