Was ist der Unterschied zwischen einem Array und einem Stack?

10

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?

Dynamisch
quelle
5
Wie wird Ihre Frage nicht von dem beantwortet, was Sie in Wikipedia gefunden haben? Sie können in beliebiger Reihenfolge auf die Elemente eines Arrays zugreifen. Auf einen Stapel muss in LIFO-Reihenfolge zugegriffen werden.
Caleb
8
@Caleb Nur weil du etwas liest, heißt das nicht, dass du das Konzept verstehst. In meinen Gedanken verstand ich das nicht ganz, bis ich fragte.
Dynamisch
3
-1 Sie haben die Antwort grundsätzlich in Ihrer eigenen Frage gepostet. Was fragst du nochmal?
Andres F.
1
@AndresF. Ich kann nicht herausfinden, was das bedeutet ... Wenn Sie sich einen Wikipedia-Artikel ansehen und verstehen könnten, was sie zum ersten Mal sagen, wäre die Welt perfekt.
Dynamisch
2
Ich habe gerade meta.programmers gelesen und verstanden, warum Sie diese Nicht-Frage gestellt haben: Es ist für einen Wettbewerb. Ich bezweifle ernsthaft, dass Sie den Wikipedia-Artikel nicht verstanden haben. Schande über dich: /
Andres F.

Antworten:

45

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, Peekund Pop, 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.)

Mason Wheeler
quelle
11
Holzklötze - schöne Analogie
Jesse Black
1
Sie sagen "In einem Stapel gibt es keine Operation mit wahlfreiem Zugriff", aber ich bin anderer Meinung und werde meiner Antwort weitere Details hinzufügen.
Scott Whitlock
Stapel sind definitiv mit wahlfreiem Zugriff implementiert
old_timer
4
Sie müssen an Jenga saugen.
DisgruntledGoat
1
@ Mason, ich weiß. Es war ein Scherz.
DisgruntledGoat
6

In einem reinen Stapel, die einzige zulässigen Operationen sind Push, Popund Peekdoch in der Praxis, das ist nicht ganz richtig. Oder besser gesagt, die PeekOperation 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.

Scott Whitlock
quelle
Für mich ist das die Antwort. Die Frage, was der Unterschied zwischen einem Array und einem Stapel ist, hängt davon ab, warum wir einen Stapel benötigen, wenn das Array weniger eingeschränkt und vielseitiger erscheint. Und das beantwortet es: Gerade weil der Stack stärker eingeschränkt ist, macht die Verwendung in geeigneten Fällen (z. B. Funktionsaufrufe hier) das Implement logisch. Henco "die Schönheit"
Todanley
4

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

chrisjleaf
quelle
3

Ihre Verantwortlichkeiten sind unterschiedlich:

  • 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

CodeART
quelle
3

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.

Jesse Black
quelle
0

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
1
Im Bereich "Strukturen zum Speichern von Objektsammlungen" würde ich nicht sagen, dass sie sehr ähnlich sind. Im Bereich der Programmierkonzepte würde ich sagen, dass sie ziemlich ähnlich sind. Im Bereich der Dinge im Allgemeinen würde ich sagen, dass sie fast identisch sind.
Kirk Broadhurst
0

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.

FrustratedWithFormsDesigner
quelle
0

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.

Oldtimer
quelle