Im Idealfall verwenden Sie Klassen, die die Funktionsweise von Dingen in der realen Welt widerspiegeln, oder erstellen diese nach Bedarf, die Dinge, die Sie im Code modellieren. Solche Klassen geben uns ein Abstraktionsniveau, so dass wir in Bezug auf das, was wir modellieren / simulieren, kodieren können. Zusätzlich hilft die Verwendung eines vertrauten Paradigmas, wenn eine komplexe Sache codiert wird. Um zu sagen: Oh, diese Fuzzinator-Klasse benutzt einen Stack. Ich weiß, was ein Stapel ist und wie er funktioniert.
Zweitens gibt uns diese höhere Abstraktionsklasse Code, der funktioniert (wir gehen davon aus, dass das .NET-Framework getestet wurde) und erspart uns die Zeit und den Schmerz, das Rad neu zu erfinden.
Drittens ist der Code leichter zu lesen, leichter zu verstehen, einfacher zu ändern und so weiter. Es ist wartungsfreundlicher.
Die Verwendung von Klassen mit verfeinerter Funktionalität hilft dabei, zu begrenzen, wie wir es möglicherweise vermasseln.
Im Allgemeinen ist Ihre Anwendung einfach besser , wenn sie auf geeigneten Abstraktionsebenen codiert ist.
Stack ist eine dieser Klassen.
Mein HP-41X Rechner berechnet seine Arithmetik mit einem Stack. Diese Berechnungsmethode heißt RPN - Reverse Polish Notation.
Wenn ich eine Cafeteria simulieren würde, wäre der Stack perfekt für diesen Stapel von Platten. Die Platten kommen von oben auf und ab. Nicht die Mitte, nicht das Ende; nur die Spitze. Ein Stapel. Ich kann nur Push () und Pop () Platten, die den Code einfacher und klarer macht.
Stellen Sie sich alternativ eine Codierung mit dem C # -Aquivalent von subatomaren Partikeln vor - generische Sammlung oder generische IEnumerable, usw. Am Ende benutze ich allgemeine Hilfsmethoden und Eigenschaften mit allgemeinen Namen mit multivariablen Zahlen von Parametern, die in der Gesamtheit die Daten verdecken Tatsache, dass ich Platten stapeln.
Tiefe der ersten Baumdurchquerung . Im Gegensatz zu einer Warteschlange, für Breite erste Traversierung des Baumes.
Verwalten der Darstellung verschiedener Bildschirme für einen Benutzer, während er sich darin bewegt. Wenn ein Bildschirm angezeigt wird, wird er auf den Stapel geschoben. Zeichne den oberen Bildschirm.
Wenn Sie eine Sammlung möchten, in der Sie Dinge hinzufügen können und immer wissen, wann Sie etwas erhalten, ist dies das zuletzt hinzugefügte.
Implementierung der Undo / Redo-Funktionalität.
Wenn Sie Ausdruckauswertung und Syntaxanalyse durchführen, könnte der Stack eine nützliche Datenstruktur sein.
Hier ist eine Möglichkeit, wie ich Stack benutzt habe:
Ich habe eine assistentenähnliche Seite, auf der 5 Benutzersteuerelemente angezeigt werden, die in einer bestimmten Reihenfolge angezeigt und verarbeitet werden müssen. Der Benutzer sollte jederzeit in der Lage sein, zur letzten Seite der Reihe nach zurückzukehren.
Ich verwende einen stackbasierten Zustandsautomaten, um den Fortschritt des Benutzers durch den Assistenten zu verfolgen.
Jedes Mal, wenn sie sich vorwärts bewegen, schiebe ich den Zustand des Zustandsautomaten in einen gespeicherten Stack, und wenn sie zurückgehen wollen, platziere ich den oberen Wert und setze den Automaten auf den neuen obersten Stack-Wert. (Die wiederum zeigt und lädt die richtige Kontrolle)
Noch eins:
Ich musste eine Installationsanwendung für einige sehr benutzerdefinierte Serveranwendungen erstellen. Was ich am Ende getan habe, war jeden Schritt der Installation in seine eigene generische Komponente zu brechen, dh eine Komponente, um eine Datei zu kopieren, eine Komponente, um einen Registrierungswert zu schreiben, ect. Jede Komponente hatte Methoden: Führen Sie die Installationsaktion aus, und machen Sie die Installationsaktion rückgängig.
Bei jedem Schritt der Installation wird die Komponente in einen Stapel geschoben.
Jetzt, zu jeder Zeit, habe ich einen Fehler, wir knallen einfach jede Komponente vom Stapel und führen die Rückgängig-Aktion aus, die uns feinkörnige Installationstransaktionen gibt.
Stacks sind dein Freund!
Stack und Queue verwenden intern ein Array. Wenn Sie Arrays auf intelligente Weise verwenden, ist die Wahrscheinlichkeit gut, dass Sie sie bereits in einem Stapel oder einer Warteschlange wie Mode verwendet haben. Normalerweise müssen Sie sich zwischen Stack und Queue entscheiden. Ein typisches Beispiel, bei dem ein Stack benötigt wird, ist erste Tiefensuche . Wenn Sie die Sammlung in eine Warteschlange ändern, haben Sie eine erste Suche in der Breite implementiert.
Ein anderes Beispiel ist schweres Multithreading, bei dem Sie Daten zwischen einem Produzenten und einem Verbraucher über einen Stapel übergeben, wenn die Verarbeitungsreihenfolge nicht relevant ist. Das Grundprinzip dahinter ist, dass es für die CPU besser ist, den neuesten hinzugefügten Datenblock für die weitere Verarbeitung auf dem anderen Thread zu verwenden, um eine bessere Cache-Lokalität zu erhalten, wenn viele Daten verarbeitet werden.
Und die Liste geht weiter ....
Stapel werden häufig in Textanalysealgorithmen verwendet, wie z. B. bei der Auswertung von "4 + 5 + 6". Ein praktisches Beispiel für eine Anwendung, die Stapel zum Parsen von Text verwendet, finden Sie unter HTMLAgilityPack . Diese Komponente wird zum Parsen von HTML verwendet und enthält den Quellcode, damit Sie sehen können, wie und wo die Stapel verwendet werden ...
Stapel sind nützlich, wenn Sie einen Ausdruck von einer Infix-Notation in eine Präfix-Notation konvertieren. Zum Beispiel:
a + b
bis (+ a b)
Ich würde sagen, wenn Sie etwas modellieren würden, das konzeptionell ein Stapel ist. Angenommen, Sie modellieren eine kleine, aber tiefe Schublade und Sie legen Bücher in die Schublade. Dies wird einem "First In, Last Out" -Paradigma folgen, was im Allgemeinen der Punkt eines Stacks ist.
Sie haben keine Liste von Büchern oder irgendeine Art von Aufzählung - Sie haben eine bestimmte Reihenfolge von ihnen ... nämlich das Gegenteil der Reihenfolge, in der sie hinzugefügt wurden.
Stack<T>
scheint wirklich eine Untermenge von List<T>
zu sein (mit ein paar umbenannten Methoden), also stimme ich zu, dass sie nicht selbst die nützlichste Sammlung ist. Wenn es intern in einem Algorithmus verwendet wird, kann List<T>
es leicht ersetzen, auch wenn das etwas weniger idiomatisch ist.
Das Erzwingen des Stack-Verhaltens ist nur erforderlich, wenn es öffentlich verfügbar gemacht wird. Aber in diesem Fall ist es normalerweise eine bessere Idee, eine Art Wrapper über die interne Sammlung zu legen, also scheint es auch nicht wirklich nützlich zu sein. Ich würde sicherlich die Verwendung für eine IStack<T>
-Schnittstelle sehen, aber nicht so sehr für eine einfache Sammlungsklasse Stack<T>
.
Meine Schlussfolgerung ist, dass ich keine Stack<T>
Klasse in das Framework aufgenommen hätte, nur eine IStack<T>
Schnittstelle. Die BCL-Kollektionen sehen mir im Allgemeinen nicht besonders gut aus.
ConcurrentStack<T>
scheint dagegen viel nützlicher zu sein.
Das Verfolgen des Browserverlaufs ist eine Verwendung für den Stapel. Auch "rückgängig machen" für Änderungen usw. In ähnlicher Weise verwenden einige Lagerverwaltungssysteme Stapel und Warteschlangen zum Verwalten der Reihenfolge, in der Artikel für Sendungen ausgewählt werden müssen.
Tags und Links c# data-structures