Betrachten Sie die folgende Einstellung:
- Wir erhalten einen Stapel der Elemente enthält .n
- Wir können eine konstante Anzahl von zusätzlichen Stapeln verwenden.
- Wir können die folgenden Operationen auf diese Stapel anwenden:
- Überprüfen Sie, ob ein Stapel leer ist.
- Vergleichen Sie die Top-Artikel von zwei Stapeln,
- lösche den obersten Gegenstand in einem Stapel,
- Drucke den obersten Gegenstand in einem Stapel,
- Kopieren Sie das oberste Element eines Stapels in einen anderen Stapel.
- Kopieren Sie den Inhalt eines Stapels auf einen anderen Stapel.
Beachten Sie, dass dies die einzigen Operationen sind, die zulässig sind. Wir können keine Gegenstände tauschen und wir dürfen keine Gegenstände auf einen der Stapel schieben, mit Ausnahme des Kopierens des obersten Gegenstands in einen Stapel (danach wird der vorherige Inhalt des Zielstapels verworfen und enthält nur den kopierten Gegenstand). .
Hier ist ein Algorithmus zum Sortieren der Stapel mit -Vergleichen:
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
Können wir es besser machen?
Gibt es ein Programm, das die sortierte Liste der Elemente in den Stapeln nur mit -Vergleichen druckt ?
ds.algorithms
sorting
Siddharth
quelle
quelle
Antworten:
Ich denke, ich kann jetzt eine nichttriviale Untergrenze demonstrieren. Die Idee ist, ein solches Programm mit einer Familie von Vergleichsverzweigungsprogrammen zu implementieren. Die "Nur-Lese" -Annahme bedeutet, dass unsere Familie von Verzweigungsprogrammen nur wenig Platz benötigt, dh . Dann wenden wir die untere Grenze S T = Ω ( n 2 ) an , die von Borodin et al. in "Ein Time-Space-Tradeoff für das Sortieren auf nicht vergessenen Maschinen." Dies gibt uns eine Untergrenze von n 2 / log n für die Zeit.O (logn ) ST=Ω(n2) n2/logn
Im Detail: Auf die obige Operation 5 können wir verzichten. Wenn wir schon die Köpfe zweier Listen vergleichen und den Kopf einer Liste ausdrucken können, brauchen wir den Kopf einer Liste nicht in einem bestimmten Register zu isolieren. Angenommen, wir sehen, dass jedes Register in der Maschine immer nur eine letzte Teilzeichenfolge der Eingabe speichert.
Angenommen, unser Registerprogramm hat Codezeilen und k Register, X 1 , … , X k .ℓ k X1,…,Xk
Fix . Wir konstruieren das Vergleichsverzweigungsprogramm für Zeichenketten der Länge n wie folgt. Erstellen Sie einen Knoten für jedes Tupel ( i , d 1 , … , d k ) mit 1 ≤ i ≤ ℓ und 0 ≤ d 1 , … , d k ≤ n . Die Idee ist, dass Berechnungen in der Registermaschine Pfaden im Verzweigungsprogramm entsprechen und wir uns am Knoten ( i , d 1 , … , dn n (i,d1,…,dk) 1≤i≤ℓ 0≤d1,…,dk≤n , wenn wir anLinie sind i im Register Maschine und die Länge des Strings gespeichert in X i ist d i . Nun müssen wir die gerichteten Kanten des Verzweigungsprogramms definieren(i,d1,…,dk) i Xi di
Wenn Zeile von der Form isti
wenn dann gehe zu i 1 sonst gehe zu i 2Xu<Xv i1 i2
dann für all , den Knoten ( i , d 1 , ... , d k ) wird durch Vergleichen des markierten d u ' ten und d v -te Element der Eingabe, und die "wahren" edge gehen zu müssen , um ( i 1 , d 1 , … , d k ) und die "falsche" Kante zu ( i 2 , d 1 , … , d kd1,…,dk (i,d1,…,dk) du dv (i1,d1,…,dk) .(i2,d1,…,dk)
Wenn Zeile von der Form istich
, gehe zur Linie i 'X1← t a i l ( X2) ich′
dann gibt es einen Pfeil von einem beliebigen Knoten zu ( i ' , d 2 - 1 , … , d k ) .( i , d1, … , Dk) ( i′, d2- 1 , … , dk)
Wenn Zeile von der Form istich
, gehe zur Linie i 'print(head(Xu)) i′
dann gibt es einen Pfeil von jedem Knoten bis ( i ' , d 1 , ... , d k ) , die durch den gekennzeichnet ist d u -ten Knoten des Einganges.(i,d1,…,dk) (i′,d1,…,dk) du
Hoffentlich machen diese Beispiele deutlich, wie ich mein Verzweigungsprogramm aufbauen will. Wenn alles gesagt und getan ist , diese Verzweigung Programm hat höchstens Knoten, so dass es Raum hat O ( log n )l ⋅ nk O ( logn )
quelle
Können Sie Elemente zählen? Dann, denke ich, gibt es eine ziemlich einfache Mergesort-Implementierung. Wenn Sie zusätzliche Symbole auf den Stapel legen könnten, könnten Sie dies mit 3 Stapeln wie folgt lösen:
Wenn wir nur ein Element haben, ist die Liste bereits sortiert. Nehmen wir nun an, wir haben die obere Hälfte des Stapels bereits sortiert. Wir können die obere Hälfte (in umgekehrter Reihenfolge) auf den zweiten Stapel kopieren und ein Trennsymbol darauf platzieren. Jetzt haben wir wieder 3 Stapel (da wir die bereits sortierten Symbole unterhalb des Trennsymbols ignorieren können) und können die untere Hälfte sortieren. Schließlich können wir die sortierte untere Hälfte in umgekehrter Reihenfolge auf einen dritten Stapel kopieren und beide Hälften wieder zum ursprünglichen Stapel zusammenführen.
Alle Operationen kosten lineare Zeit, daher haben wir die Liste in O ( n log n ) sortiertO (nlogn )
(Beachten Sie, dass wir aufgrund der Trennsymbole Stapel der Größe benötigen , dies kann jedoch leicht durch Verwendung eines anderen Stapels korrigiert werden.)n logn
Da Sie keine neuen Elemente auf den Stapel legen können, können Probleme an den Trennungspunkten auftreten. Um dies zu lösen, können Sie mit einigen zusätzlichen Stapeln Folgendes tun:
quelle