Technologieaustausch

Datenstrukturstapel

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Öffnung

Hallo Freunde! Lasst uns heute gemeinsam die Datenstruktur des Stapels lernen!

1. Stapeln

1.1 Grundkonzepte des Stapels

Stapel: Eine spezielle lineare Liste, die nur Einfüge- und Löschvorgänge an einem festen Ende zulässt. Das Ende, an dem die Dateneinfügungs- und -löschvorgänge eingegeben werden, wird als oberes Ende des Stapels bezeichnet, und das andere Ende wird als unteres Ende des Stapels bezeichnet.Datenelemente im Stapel entsprechenLIFO (Last In First Out)-Prinzip. Wir können es uns so vorstellen, als würden wir Hammelkebabs essen,Ziehen Sie es zuerst anDie Hammelfleischstücke werden hineingedrücktuntender LetzteDie Hammelstücke sind daAn der Spitzevon.

Schieben des Stapels: Der Einfügevorgang des Stapels wird Push/Push/Push genannt.Fügen Sie Daten von oben in den Stapel ein

Pop: Der Löschvorgang des Stapels wird als Popping bezeichnet.Die ausgehenden Daten liegen ebenfalls oben auf dem Stapel

1.2 Implementierung des Stapels

Der Stapel kann im Allgemeinen mithilfe eines Arrays zur Implementierung des Stapels oder mithilfe einer verknüpften Liste zur Implementierung des Stapels implementiert werden, je nachdem, was relativ gesehen besser istArray-StrukturDie Implementierung des Stacks ist einfacher und effizienter.

Denn bei der Implementierung werden die Schnittstellen zum Hinzufügen, Löschen, Ändern und Abfragen der vorherigen Sequenztabelle implementiert (Datenstruktur-Sequenztabelle) Es ist für uns sehr praktisch, die Struktur des Arrays zum Einfügen und Löschen am Ende zu verwenden. Daher definieren wir bei der Implementierung des Stapels das Ende des Arrays als die Oberseite des Stapels und den Kopf als die Unterseite der Stapel.


2. Implementierung der Stack-Schnittstelle

Der Stapel kann wie die Sequenzliste als statischer Stapel fester Länge oder als dynamisch wachsender Stapel ausgelegt sein.Da der Stapel mit fester Länge große Einschränkungen aufweist und in der Praxis nicht praktikabel ist, implementieren wir hauptsächlich UnterstützungDynamisch wachsender Stapel

Wie bei der vorherigen Implementierung der Sequenzlisten-/verknüpften Listenschnittstelle erstellen wir zunächst eine Header-Datei „Stack.h“ und zwei Quelldateien „Stack.c“ und „Test.c“. Die spezifischen Funktionen sind:

Stack.hStack-Definition, Header-Dateireferenz und Schnittstellenfunktionsdeklaration
Stapel.cImplementierung von Schnittstellenfunktionen
Test.cTesten Sie jede Funktion

Lassen Sie uns zunächst den vollständigen Code von „Stack.h“ zeigen. Vergessen Sie nicht, „Stack.h“ in den beiden Quelldateien anzugeben

  1. #pragma once //防止头文件被二次引用
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<assert.h>
  5. typedef int ElemType; //如果要修改存储的数据类型可直接在此修改
  6. typedef struct Stack {
  7. ElemType* arr; //动态数组
  8. int top; //栈顶
  9. int capacity; //容量
  10. }Stack;
  11. void StackInit(Stack* ps);//初始化栈
  12. void StackPush(Stack* ps, ElemType x);//入栈
  13. void StackPop(Stack* ps);//出栈
  14. ElemType StackTop(Stack* ps);//获取栈顶元素
  15. int StackSize(Stack* ps);//获取栈中有效元素的个数
  16. int StackEmpty(Stack* ps);//检测栈是否为空,如果为空返回非零结果,如果不为空返回0
  17. void StackDestroy(Stack* ps);//销毁栈

Unter diesen wird die Bedeutung von „oben“ durch den Anfangswert bestimmt, der im Folgenden ausführlich erläutert wird. Als nächstes beginnen wir mit der Implementierung der Schnittstelle.

(1) Initialisierungsstapel
  1. //初始化栈
  2. void StackInit(Stack* ps) {
  3. assert(ps); //断言,防止传入空指针
  4. ps->arr = NULL; //初始化数组,置空
  5. ps->capacity = 0;//top指向栈顶元素的下一个位置
  6. ps->top = 0; //初始化容量
  7. }

Zum besseren Verständnis verstehen wir oben in der Struktur ungefähr den Index des Arrays.Wenn wir beim Initialisieren des Stapels top auf 0 initialisieren, befinden sich keine Daten im Stapel und top zeigt auf die nächste Position der obersten Daten im Stapel.

Wenn wir top auf -1 initialisieren, zeigt top auf die Position der obersten Daten auf dem Stapel. Es ist für uns besser, es hier auf 0 zu initialisieren, da es praktisch ist, Elemente hinzuzufügen und Elemente zu löschen.

(2) In den Stapel schieben
  1. //入栈
  2. void StackPush(Stack* ps, ElemType x) {
  3. //扩容
  4. if (ps->capacity == ps->top) //容量已满,需要扩容
  5. {
  6. //如果容量为0,则扩容到4; 否则扩大2
  7. int newCapacity = ps->capacity == 0 ? 4 : 2 * (ps->capacity);
  8. //创建一个临时指针变量来存储新空间地址,防止开辟失败
  9. ElemType* temp = realloc(ps->arr, newCapacity * sizeof(ElemType));
  10. if (temp == NULL) //防止开辟失败出现空指针
  11. {
  12. perror("realloc fail!n");
  13. exit(1);
  14. }
  15. ps->arr = temp; //将临时指针变量中存放的新空间地址赋给arr
  16. ps->capacity = newCapacity;//空间容量更新
  17. }
  18. ps->arr[ps->top] = x;//将数据存放进栈顶元素的下一个位置
  19. ps->top++;//位置更新
  20. }

Da es einen Unterschied zwischen dem Stapel und der Sequenztabelle gibt, können wir die Elemente im Stapel nicht direkt durchlaufen und drucken. Daher müssen wir die Funktionen StackEmpty und StackPop verwenden, die später erläutert werden .

(3) Herausspringen
  1. //出栈
  2. void StackPop(Stack* ps) {
  3. assert(ps); //断言,防止传入空指针
  4. assert(ps->top); //断言,防止栈中没有元素,却还在执行删除
  5. ps->top--; //top指针往前挪动一位(相当于这个位置被覆盖了)
  6. }
(4) Holen Sie sich das oberste Element des Stapels
  1. //获取栈顶元素
  2. ElemType StackTop(Stack* ps) {
  3. assert(ps); //断言,防止传入空指针
  4. assert(ps->top); //断言,防止栈为空
  5. return ps->arr[ps->top - 1];//top-1为栈顶元素的位置,返回其值
  6. }
(5) Ermitteln Sie die Anzahl der gültigen Elemente im Stapel
  1. //获取栈中有效元素的个数
  2. int StackSize(Stack* ps) {
  3. assert(ps); //断言,防止传入空指针
  4. return ps->top; //top即为有效元素的个数
  5. }
(6) Prüfen Sie, ob der Stapel leer ist
  1. //检测栈是否为空,如果为空返回非零结果,如果不为空返回0
  2. int StackEmpty(Stack* ps) {
  3. assert(ps); //断言,防止传入空指针
  4. return ps->top == 0; //如果top==0, 说明栈为空
  5. }

Aus diesem Grund muss StackEmpty in der vorherigen Behauptung hinzugefügt werdenlogischer NegationsoperatorDer Grund dafür ist, dass StackEmpty true zurückgibt, wenn der Stapel leer ist, und die Negation von false beweisen kann, dass sich Elemente im Stapel befinden.

(7) Zerstöre den Stapel
  1. //销毁栈
  2. void StackDestroy(Stack* ps) {
  3. assert(ps); //断言,防止传入空指针
  4. if (ps->arr) //如果动态数组有效
  5. {
  6. free(ps->arr); //释放arr
  7. ps->arr = NULL; //将arr置空
  8. }
  9. ps->capacity = 0; //数组的容量为0
  10. ps->top = 0; //数组的栈顶top0
  11. }

Nachdem alle Schnittstellen fertiggestellt sind, testen wir den Code in Test.c:

Lass es uns noch einmal testen:

Überhaupt kein Problem. Herzlichen Glückwunsch zur Fertigstellung der Stack-Schnittstelle! Das Folgende ist der vollständige Code der Datei „Stack.c“:

  1. #include"Stack.h"
  2. //初始化栈
  3. void StackInit(Stack* ps) {
  4. assert(ps); //断言,防止传入空指针
  5. ps->arr = NULL; //初始化数组,置空
  6. ps->capacity = 0;//top指向栈顶元素的下一个位置
  7. ps->top = 0; //初始化容量
  8. }
  9. //入栈
  10. void StackPush(Stack* ps, ElemType x) {
  11. //扩容
  12. if (ps->capacity == ps->top) //容量已满,需要扩容
  13. {
  14. //如果容量为0,则扩容到4; 否则扩大2
  15. int newCapacity = ps->capacity == 0 ? 4 : 2 * (ps->capacity);
  16. //创建一个临时指针变量来存储新空间地址,防止开辟失败
  17. ElemType* temp = realloc(ps->arr, newCapacity * sizeof(ElemType));
  18. if (temp == NULL) //防止开辟失败出现空指针
  19. {
  20. perror("realloc fail!n");
  21. exit(1);
  22. }
  23. ps->arr = temp; //将临时指针变量中存放的新空间地址赋给arr
  24. ps->capacity = newCapacity;//空间容量更新
  25. }
  26. ps->arr[ps->top] = x;//将数据存放进栈顶元素的下一个位置
  27. ps->top++;//位置更新
  28. }
  29. //出栈
  30. void StackPop(Stack* ps) {
  31. assert(ps); //断言,防止传入空指针
  32. assert(ps->top); //断言,防止栈中没有元素,却还在执行删除
  33. ps->top--; //top指针往前挪动一位(相当于这个位置被覆盖了)
  34. }
  35. //获取栈顶元素
  36. ElemType StackTop(Stack* ps) {
  37. assert(ps); //断言,防止传入空指针
  38. assert(ps->top); //断言,防止栈为空
  39. return ps->arr[ps->top - 1];//top-1为栈顶元素的位置,返回其值
  40. }
  41. //获取栈中有效元素的个数
  42. int StackSize(Stack* ps) {
  43. assert(ps); //断言,防止传入空指针
  44. return ps->top; //top即为有效元素的个数
  45. }
  46. //检测栈是否为空,如果为空返回非零结果,如果不为空返回0
  47. int StackEmpty(Stack* ps) {
  48. assert(ps); //断言,防止传入空指针
  49. return ps->top == 0; //如果top==0, 说明栈为空
  50. }
  51. //销毁栈
  52. void StackDestroy(Stack* ps) {
  53. assert(ps); //断言,防止传入空指针
  54. if (ps->arr) //如果动态数组有效
  55. {
  56. free(ps->arr); //释放arr
  57. ps->arr = NULL; //将arr置空
  58. }
  59. ps->capacity = 0; //数组的容量为0
  60. ps->top = 0; //数组的栈顶top0
  61. }

Übungsteil

1. Welche der folgenden Aussagen zu Stapeln ist richtig ( )

A. Der Stapel ist eine „First In First Out“-Datenstruktur

B. Der Stapel kann mithilfe einer verknüpften Liste oder einer sequentiellen Liste implementiert werden

C. Der Stapel kann nur Daten am unteren Ende des Stapels einfügen

D. Der Stack kann keine Daten löschen

korrekte Antwort: B

Ein Fehler: Der Stapel ist eine Last-In-First-Out-Datenstruktur und die Warteschlange ist First-In, First-Out.

B ist richtig: Sowohl Sequenzlisten als auch verknüpfte Listen können zum Implementieren von Stapeln verwendet werden, aber Sequenzlisten werden im Allgemeinen verwendet, da der Stapel als kastrierte Version der Sequenzliste betrachtet wird. Nur die Schwanzeinfügungs- und Schwanzlöschoperationen der Sequenztabelle Die Endeinfügung und die Endlöschung der Sequenztabelle erfordern keine beweglichen Elemente und sind sehr effizient. Daher werden sie im Allgemeinen mithilfe sequentieller Tabellen implementiert.

C-Fehler: Der Stapel kann Eingabeeinfügungs- und -löschvorgänge nur oben im Stapel ausführen

D-Fehler: Der Stapel verfügt über Push- und Pop-Operationen, um ein Element aus dem Stapel zu löschen.

2. Die Push-Sequenz eines Stapels ist ABCDE und die unmögliche Pop-Sequenz ist ( )

A.ABCDE

B.EDCBA

C.DCEBA

D.ECDBA

korrekte Antwort: D

Wenn E zuerst herauskommt, bedeutet dies, dass ABCDE vollständig auf den Stapel geschoben wurde. Nachdem E aus dem Stapel entfernt wurde, ist das oberste Element des Stapels D. Wenn es erneut herausspringt, sollte es D und nicht C sein .

Daher sollte D ausgewählt werden

3. Im Vergleich zum sequentiellen Stapel sind die offensichtlichen Vorteile des Kettenstapels ( )

A. Der Einfügevorgang ist bequemer

B. Der Löschvorgang ist bequemer

C. Beim Einschieben in den Stapel ist keine Erweiterung erforderlich

korrekte Antwort: C

Fehler A. Wenn es sich um einen Kettenstapel handelt, sind im Allgemeinen Vorgänge zum Einfügen oder Löschen des Kopfes erforderlich, während bei einem sequentiellen Stapel im Allgemeinen Vorgänge zum Einfügen und Löschen des Endes ausgeführt werden. Die Operation einer verknüpften Liste ist komplizierter als die einer sequentiellen Tabelle Es ist einfacher, eine sequentielle Struktur zum Implementieren eines Stapels zu verwenden.

B ist falsch. Den Grund finden Sie bei A.

C ist korrekt. Wenn der Stapel in einer Kettenstruktur implementiert ist, entspricht jeder Push in den Stapel dem Einfügen eines Knotens in den Kopf der verknüpften Liste.

4. Welche der folgenden Aussagen zur Verwendung von Stacks zur Implementierung von Warteschlangen ist falsch ( )

A. Durch die Stapelsimulation zum Implementieren einer Warteschlange können zwei Stapel verwendet werden, ein Stapel simuliert das Betreten der Warteschlange und ein Stapel simuliert das Verlassen der Warteschlange.

B. Jedes Mal, wenn Sie die Warteschlange entfernen, müssen Sie alle Elemente in einem Stapel in einen anderen Stapel importieren und ihn dann herausnehmen.

C. Wenn Sie in die Warteschlange eintreten, speichern Sie die Elemente einfach direkt im Stapel, der das Eintreten in die Warteschlange simuliert.

D. Die zeitliche Komplexität der Warteschlangenoperation beträgt O(1)

korrekte Antwort: B

Bei Option B simuliert ein Stapel das Eintreten in die Warteschlange und ein Stapel das Entnehmen aus der Warteschlange. Wenn der Stapel leer ist, werden alle Elemente im simulierten Warteschlangenstapel importiert . Es ist notwendig, jedes Mal Elemente zu importieren, daher ist es falsch.

Bei Option A sind die Eigenschaften von Stapeln und Warteschlangen entgegengesetzt. Ein Stapel kann keine Warteschlange implementieren.

Bei Option C simuliert ein Stapel das Betreten der Warteschlange und ein Stapel das Verlassen der Warteschlange. Beim Betreten der Warteschlange werden die Elemente direkt in dem Stapel gespeichert, der das Betreten der Warteschlange simuliert.

In Option D bedeutet Warteschlangen, Elemente auf den Stapel zu legen, sodass die Zeitkomplexität O(1) beträgt.

Ende

Heute haben wir etwas über die Datenstruktur eines Stapels erfahren. Ist das nicht viel einfacher als eine verknüpfte Liste? Ich hoffe, dieser Artikel wird meinen Freunden hilfreich sein!!!

bittenLiken, favorisieren und folgen!!!

Danke euch allen! ! !