Eine ähnliche Frage wurde früher gefragt , dort , aber die Frage hier ist das Gegenteil davon, unter Verwendung von zwei Warteschlangen als Stapel. Die Frage...
Gegeben seien zwei Warteschlangen mit ihren Standard - Operationen ( enqueue
, dequeue
, isempty
, size
), implementieren einen Stapel mit seinen Standard - Operationen ( pop
, push
, isempty
, size
).
Es sollte zwei Versionen der Lösung geben.
- Version A : Der Stapel sollte beim Schieben eines Elements effizient sein. und
- Version B : Der Stapel sollte beim Poppen eines Elements effizient sein.
Ich interessiere mich mehr für den Algorithmus als für bestimmte Sprachimplementierungen. Ich begrüße jedoch Lösungen, die in mir vertrauten Sprachen ausgedrückt werden (Java,c #,Python,vb,Javascript,php).
algorithm
data-structures
stack
TechTravelThink
quelle
quelle
Pop
in $ O (1) $ undPush
in $ O (\ sqrt {n}) $ amortisierter Zeit gearbeitet wird.Antworten:
Version A (effizienter Push):
Version B (effizienter Pop):
quelle
Der einfachste (und vielleicht einzige) Weg, dies zu tun, besteht darin, neue Elemente in die leere Warteschlange zu verschieben, die anderen in die Warteschlange zu stellen und in die zuvor leere Warteschlange zu stellen. Auf diese Weise steht immer das Neueste an der Spitze der Warteschlange. Dies wäre Version B, für Version A kehren Sie den Vorgang einfach um, indem Sie die Elemente mit Ausnahme der letzten in die zweite Warteschlange einreihen.
Schritt 0:
Schritt 1:
Schritt 2:
Schritt 3:
quelle
Wir können dies mit einer Warteschlange tun:
drücken:
n
die Anzahl der Elemente in der Warteschlange ist, entfernen Sie die Elementzeiten und fügen Sie sie einn-1
.Pop:
.
Beispielimplementierung:
quelle
quelle
Können wir nur eine Warteschlange verwenden, um einen Stapel zu implementieren? Ich kann zwei Warteschlangen verwenden, aber es wäre effizienter, eine einzelne Warteschlange in Betracht zu ziehen. Hier ist der Code:
quelle
quelle
Hier ist meine Antwort - wo der "Pop" ineffizient ist. Es scheint, dass alle Algorithmen, die sofort in den Sinn kommen, eine N-Komplexität haben, wobei N die Größe der Liste ist: ob Sie sich für die Arbeit am 'Pop' oder für die Arbeit am 'Push' entscheiden.
Der Algorithmus, bei dem Listen zurück und viertens gehandelt werden, ist möglicherweise besser, da keine Größenberechnung erforderlich ist, obwohl Sie immer noch eine Schleife erstellen und mit leer vergleichen müssen.
Sie können beweisen, dass dieser Algorithmus nicht schneller als N geschrieben werden kann, indem Sie feststellen, dass die Informationen über das letzte Element in einer Warteschlange nur verfügbar sind, wenn Sie die Größe der Warteschlange kennen, und dass Sie Daten zerstören müssen, um zu diesem Element zu gelangen, daher die zweite Warteschlange .
Die einzige Möglichkeit, dies zu beschleunigen, besteht darin, überhaupt keine Warteschlangen zu verwenden.
quelle
Hier ist meine Lösung, die im Durchschnitt für O (1) funktioniert. Es gibt zwei Warteschlangen:
in
undout
. Siehe Pseudocode unten:quelle
Wie bereits erwähnt, würde nicht eine einzige Warteschlange den Trick machen? Es ist wahrscheinlich weniger praktisch, aber etwas schlauer.
quelle
Hier ist ein einfacher Pseudocode: Push ist O (n), Pop / Peek ist O (1):
quelle
Es seien S1 und S2 die beiden Stapel, die bei der Implementierung von Warteschlangen verwendet werden sollen.
Wir stellen sicher, dass immer eine Warteschlange leer ist.
Push-Vorgang: Unabhängig davon, welche Warteschlange nicht leer ist, fügen Sie das Element ein.
Push (struct Stack *S, int data) { if(isEmptyQueue(S->Q1) EnQueue(S->Q2, data); else EnQueue(S->Q1, data); }
Zeitkomplexität: O (1)
Pop-Operation: Übertragen Sie n-1 Elemente in eine andere Warteschlange und löschen Sie sie zuletzt aus der Warteschlange, um die Pop-Operation auszuführen.
`
Zeitkomplexität: Laufzeit von Pop Operation ist O (n), da bei jedem Aufruf von Pop alle Elemente von einer Warteschlange in eine andere übertragen werden.
quelle
quelle
quelle
Hier ist noch eine Lösung:
für PUSH: - Fügen Sie das erste Element in Warteschlange 1 hinzu. - Wenn Sie ein zweites Element usw. hinzufügen, stellen Sie das Element zuerst in Warteschlange 2 in die Warteschlange und kopieren Sie dann das gesamte Element von Warteschlange 1 in Warteschlange 2. -für POP wird das Element einfach aus der Warteschlange entfernt, nachdem Sie das letzte Element eingefügt haben.
So,
}}
Es gibt ein Problem, ich kann nicht herausfinden, wie man die Warteschlangen umbenennt ???
quelle
quelle
Python-Code mit nur einer Warteschlange
quelle
Hier ist der vollständige Arbeitscode in c #:
Es wurde mit Single Queue implementiert,
drücken:
Pop:
quelle
Hier ist eine sehr einfache Lösung, die eine Warteschlange verwendet und Funktionen wie Stack bietet.
In der obigen Klasse mit dem Namen "CustomStack" überprüfe ich nur die Warteschlange auf leer. Wenn sie leer ist, fügen Sie eine ein und von da an wird sie eingefügt und dann eingefügt. Nach dieser Logik wird zuerst zuerst kommen. Beispiel: In die Warteschlange habe ich 1 eingefügt und versuche nun, 2 einzufügen. Entfernen Sie zum zweiten Mal 1 und fügen Sie es erneut ein, damit es in umgekehrter Reihenfolge angezeigt wird.
Danke dir.
quelle
Im Folgenden finden Sie eine sehr einfache Java-Lösung, die den Push-Vorgang effizient unterstützt.
Algorithmus -
Deklarieren Sie zwei Warteschlangen q1 und q2.
Push-Operation - Element in Warteschlange q1 einreihen.
Pop-Vorgang - Stellen Sie sicher, dass die Warteschlange q2 nicht leer ist. Wenn es leer ist, entfernen Sie alle Elemente aus q1 mit Ausnahme des letzten Elements und stellen Sie es nacheinander in q2 ein. Dequeue das letzte Element von q1 und speichern Sie es als das geplatzte Element. Tauschen Sie die Warteschlangen q1 und q2 aus. Geben Sie das gespeicherte Element zurück.
Peek-Operation - Stellen Sie sicher, dass die Warteschlange q2 nicht leer ist. Wenn es leer ist, entfernen Sie alle Elemente aus q1 mit Ausnahme des letzten Elements und stellen Sie es nacheinander in q2 ein. Entfernen Sie das letzte Element aus q1 und speichern Sie es als gespähtes Element. Stellen Sie es wieder in die Warteschlange q2 und tauschen Sie die Warteschlangen q1 und q2 aus. Gibt das gespeicherte Peeked-Element zurück.
Unten ist der Code für den obigen Algorithmus -
quelle
Hier ist meine Lösung ..
Concept_Behind ::
push(struct Stack* S,int data)
:: Diese Funktion stellt das erste Element in Q1 in die Warteschlange und ruht in Q2pop(struct Stack* S)
:: Wenn Q2 nicht leer ist, werden alle Elemente in Q1 übertragen und das letzte Element in Q2 zurückgegeben. Andernfalls (was bedeutet, dass Q2 leer ist) werden alle Elemente in Q2 und übertragen gibt das letzte Element in Q1 zurückEfficiency_Behind ::
push(struct Stack*S,int data)
:: O (1) // da einzelne Enqueue pro Datenpop(struct Stack* S)
:: O (n) // da die schlechtesten n-1 Daten pro Pop übertragen werden.quelle
quelle
quelle