Laut Wikipedia ein Stapel :
ist ein abstrakter LIFO-Datentyp (Last In, First Out) und eine lineare Datenstruktur.
Während ein Array :
ist eine Datenstruktur, die aus einer Sammlung von Elementen (Werten oder Variablen) besteht, die jeweils durch mindestens einen Array-Index oder -Schlüssel gekennzeichnet sind.
Soweit ich weiß, sind sie ziemlich ähnlich. Was sind die Hauptunterschiede? Wenn sie nicht gleich sind, was kann ein Array, was ein Stapel nicht kann, und umgekehrt?
data-structures
array
stack
Dynamisch
quelle
quelle
Antworten:
Nun, Sie können sicherlich einen Stapel mit einem Array implementieren. Der Unterschied liegt im Zugang. In einem Array haben Sie eine Liste von Elementen, auf die Sie jederzeit zugreifen können. (Denken Sie an ein paar Holzklötze, die alle hintereinander angeordnet sind.)
In einem Stapel gibt es jedoch keine Operation mit wahlfreiem Zugriff. gibt es nur
Push
,Peek
undPop
, die alle auf der Oberseite des Stapels ausschließlich mit dem Elemente befassen. (Denken Sie an die Holzblöcke, die jetzt vertikal gestapelt sind. Sie können nichts unter der Turmspitze berühren, sonst fällt es um.)quelle
In einem reinen Stapel, die einzige zulässigen Operationen sind
Push
,Pop
undPeek
doch in der Praxis, das ist nicht ganz richtig. Oder besser gesagt, diePeek
Operation ermöglicht es Ihnen oft, jede Position auf dem Stapel zu betrachten, aber der Haken ist, dass sie relativ zu dem einen Ende des Stapels ist.Wie andere gesagt haben, handelt es sich bei einem Array um einen Direktzugriff, und alles bezieht sich auf den Anfang des Arrays .
In einem Stapel können Sie nur am Arbeitsende des Stapels hinzufügen / entfernen, aber Sie haben immer noch Lesezugriff, aber es wird auf das Arbeitsende verwiesen . Das ist der grundlegende Unterschied.
Wenn Sie beispielsweise Parameter auf einem Stapel an eine Funktion übergeben, muss der Angerufene die Parameter nicht entfernen, um sie anzuzeigen. Es werden nur lokale Variablen auf den Stapel verschoben und alle lokalen Variablen und Parameter basierend auf einem Versatz vom Stapelzeiger referenziert. Wenn Sie nur ein Array verwenden würden, wie würde der Angerufene dann wissen, wo er nach seinen Parametern suchen muss? Wenn der Angerufene fertig ist, löscht er seine lokalen Variablen, gibt einen Rückgabewert aus, gibt die Kontrolle an den Aufrufer zurück, und der Aufrufer gibt den Rückgabewert (falls vorhanden) und dann die Parameter vom Stapel. Das Schöne ist, dass es funktioniert, egal wie weit Sie in Ihren Funktionsaufrufen verschachtelt sind (vorausgesetzt, Ihnen geht nicht der Stapelspeicher aus).
Das ist eine bestimmte Verwendung / Implementierung, aber es zeigt den Unterschied: Array wird immer von Anfang an referenziert, aber Stapel werden immer von einer funktionierenden Endposition aus referenziert.
Eine mögliche Implementierung eines Stapels ist ein Array plus ein Index, um sich zu merken, wo sich das Arbeitsende befindet.
quelle
Ich denke, die größte Verwirrung besteht hier in der Implementierung im Vergleich zu grundlegenden Datenstrukturen.
In den meisten (grundlegenderen Sprachen) stellt ein Array einen Satz von Elementen fester Länge dar, auf die Sie zu einem bestimmten Zeitpunkt zugreifen können. Die Tatsache, dass Sie eine Reihe solcher Elemente haben, sagt nichts darüber aus, wie es verwendet werden soll (und ehrlich gesagt wird ein Computer nicht wissen / sich darum kümmern, wie Sie es verwenden, solange Sie nicht gegen die Verwendung verstoßen).
Ein Stapel ist eine Abstraktion, die zur Darstellung von Daten verwendet wird, die auf bestimmte Weise behandelt werden sollen. Dies ist ein abstraktes Konzept, da es nur besagt, dass es eine Unterroutine / Methode / Funktion haben muss, die nach oben hinzugefügt oder von oben entfernt werden kann, während Daten unter dem oberen Rand nicht berührt werden. Rein Ihre Wahl, ein Array auf diese Weise zu verwenden.
Sie können einen Stapel aus vielen verschiedenen Arten von Datenstrukturen erstellen: Arrays (mit einer maximalen Größe), dynamische Arrays (können aus Platzgründen wachsen) oder verknüpfte Listen. Persönlich bin ich der Meinung, dass eine verknüpfte Liste die Einschränkungen eines Stapels am besten darstellt, da Sie sich ein wenig anstrengen müssen, um Dinge jenseits des ersten Elements zu sehen, und es sehr einfach ist, sie der Vorderseite hinzuzufügen und von der Vorderseite zu entfernen.
Sie können also ein Array verwenden, um einen Stapel zu erstellen, aber sie sind nicht gleichwertig
quelle
Der Stapel muss in der Lage sein, Elemente auf den Stapel zu legen und Elemente vom Stapel zu verschieben, weshalb er normalerweise über Methoden
Pop()
und verfügtPush()
Die Verantwortung des Arrays besteht darin, das Element an einem bestimmten Index abzurufen / festzulegen
quelle
Sie können ein Element aus einem beliebigen Index eines A \ -Arrays abrufen.
Mit einem Stapel können Sie ein Element in der Mitte von Stapel A abrufen, indem Sie einen anderen Stapel verwenden: B.
Sie nehmen den obersten Gegenstand aus A heraus und legen ihn in B, bis Sie den gewünschten Gegenstand von A erreicht haben. Dann legen Sie die Gegenstände von B wieder auf Stapel A.
Für Daten, die das Abrufen eines beliebigen Index erfordern, ist es daher schwieriger, mit dem Stapel zu arbeiten.
In der Situation, in der Sie das Verhalten "last in, first out" wünschen, verursacht ein Stapel weniger Overhead als ein Array.
quelle
Ich würde nicht so weit gehen zu sagen, dass sie "sehr ähnlich" sind.
Ein Array wird verwendet, um Dinge zu speichern, auf die später nacheinander oder über den Index zugegriffen wird. Die Datenstruktur impliziert keine Zugriffsmethode (FIFO, LIFO, FILO usw.), kann jedoch auf Wunsch auf diese Weise verwendet werden.
Ein Stapel ist eine Möglichkeit, Dinge zu verfolgen, während sie generiert werden. Abhängig von der Art des erstellten Stapels ist eine Zugriffsmethode impliziert / erforderlich. Ein Frame-Stack wäre ein LIFO-Beispiel. Haftungsausschluss - Ich mische hier möglicherweise meine Datenstrukturtaxonomie und ein Stapel erlaubt möglicherweise nur LIFO. Andernfalls wäre es eine andere Art von Warteschlange.
Ich könnte also ein Array als Stapel verwenden (obwohl ich das nicht möchte), aber ich kann einen Stapel nicht als Array verwenden (es sei denn, ich arbeite wirklich hart daran).
quelle
Auf die Daten in einem Array kann über einen Schlüssel oder Index zugegriffen werden. Auf die Daten in einem Stapel kann zugegriffen werden, wenn sie von der Oberseite des Stapels entfernt werden. Dies bedeutet, dass der Zugriff auf Daten aus einem Array einfach ist, wenn Sie dessen Index kennen. Wenn Sie von einem Stapel aus auf Daten zugreifen, müssen Sie die Elemente so lange öffnen, bis Sie das gesuchte gefunden haben. Dies bedeutet, dass der Datenzugriff länger dauern kann.
quelle
Ein Array ist aus Sicht des Programmierers in Position und Größe festgelegt. Sie wissen, wo Sie sich darin befinden und wo sich das Ganze befindet. Sie haben Zugriff auf alles.
Mit einem Stapel sitzen Sie an einem Ende, haben aber keine Ahnung, wie groß er ist oder wie weit Sie sicher gehen können. Ihr Zugriff darauf ist auf den von Ihnen zugewiesenen Betrag beschränkt. Oft wissen Sie nicht einmal, ob Sie bei der Zuweisung des gewünschten Betrags nur auf den Heap- oder Programmbereich zugeschlagen haben. Ihre Ansicht eines Stapels ist ein kleines Array, das Sie selbst zugewiesen haben, die gewünschte Größe, die Sie steuern können und die Sie sehen können. Ihr Teil unterscheidet sich nicht von einem Array. Der Unterschied besteht darin, dass Ihr Array aus Gründen der Argumentation und Terminologie an einem Ende eines anderen Arrays angeheftet ist. Sie haben keine Sichtbarkeit, keine Ahnung, wie groß oder klein Sie sind, und Sie können es nicht berühren, ohne möglicherweise Schaden zu verursachen. Ein Array wird, sofern es nicht global ist, häufig ohnehin auf dem Stapel implementiert, sodass sich das Array und der Stapel für die Dauer dieser Funktion denselben Speicherplatz teilen.
Wenn Sie auf die Hardwareseite einsteigen möchten, ist dies natürlich prozessorspezifisch, aber im Allgemeinen basiert das Array auf einem bekannten Startpunkt / einer bekannten Adresse, die Größe ist dem Compiler / Programmierer bekannt und Adressen werden darin berechnet. Manchmal wird die Register-Offset-Adressierung verwendet (Laden Sie einen Wert aus der durch diesen Basisregisterwert definierten Adresse plus diesen Offset-Registerwert. Ebenso kann es sich beim Kompilieren um einen sofortigen Offset handeln, der nicht unbedingt auf Registern basiert, was natürlich vom Prozessor abhängt), was bei der Montage sehr wichtig ist ähnelt dem Zugriff auf ein Array in High-Level-Code. Ebenso können Sie mit dem Stapel, falls verfügbar, die Register- oder Sofortversatzadressierung verwenden, obwohl häufig ein spezielles Register verwendet wird, entweder der Stapelzeiger selbst oder ein Register, das vom Compiler / Programmierer für den Zugriff auf den Stapelrahmen reserviert wurde Funktion. Für einige Prozessoren werden spezielle Stapelzugriffsfunktionen verwendet und / oder benötigt, um auf den Stapel zuzugreifen. Sie haben Push- und Pop-Anweisungen, diese werden jedoch nicht so oft verwendet, wie Sie denken, und gelten für diese Frage nicht wirklich. Für einige Prozessoren sind Push und Pop Aliase für Anweisungen, die mit jedem Register überall verwendet werden können, nicht nur mit dem Stapelzeiger auf dem Stapel, wodurch Push und Pop nicht mehr mit dieser Frage in Verbindung gebracht werden.
quelle