当前位置:   article > 正文

数据结构之栈(LIFO)

数据结构之栈(LIFO)

一、栈的认识:

首先,栈可以被理解为一种容器,一种类似于弹夹的一边开口一边闭口的容器,这是对栈的实际理解。

其次,栈虽然也是一种数据结构,但是它并没有固定的表现形式。总而言之,栈就是一种抽象的数据结构。或言之,他就是一种数学逻辑。

最后,其实栈是寄托于数组,链表等实体进行实现的。

下面我们将讨论栈的实现。

二、栈的实现:(有两种实现方法:数组、链表)

1)基于数组的顺序栈

  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #include<stdio.h>
  3. #include<math.h>
  4. #include<stdlib.h>
  5. #include<string.h>
  6. #define MAX 101
  7. int a[MAX] = { 0 };
  8. int top = -1;
  9. //插入:
  10. void Push() {
  11. int n = 0;
  12. printf("请输入插入的数据:");
  13. scanf("%d", &n);
  14. a[++top] = n;
  15. }
  16. //弹出;
  17. void Pop() {
  18. top--;
  19. printf("删除成功!");
  20. }
  21. //返回栈顶元素;
  22. int Top() {
  23. if (top != -1) {
  24. return a[top];
  25. }
  26. else {
  27. printf("栈中没有元素了!");
  28. return top;
  29. }
  30. }
  31. void print() {
  32. for (int i = 0; i <= top; i++) {
  33. printf("%d ", a[i]);
  34. }
  35. puts("");
  36. }
  37. int main() {
  38. //基于数组实现栈:
  39. //准备一个数组,作为栈这个容器;
  40. Push();
  41. print();
  42. Push();
  43. print();
  44. Push();
  45. print();
  46. Pop();
  47. print();
  48. Top();
  49. print();
  50. }

2)基于链表的线性栈:

  1. 基于链表实现栈;
  2. 基本思想:一个单链表就是一个栈,栈顶就是链表头,因此不论是push,pop都是对头操作;
  3. 其实实现的就是链表的一个头插法,头删法;
  4. typedef struct Node {
  5. int data;
  6. struct Node* next;
  7. }Node;
  8. Node* top = NULL;//创建链表头指针,也就是栈顶的指针;
  9. Node* createNode(int n) {
  10. Node* p = (Node*)malloc(sizeof(Node));
  11. p->next = NULL;
  12. p->data = n;
  13. return p;
  14. }
  15. void Push(int n) {
  16. Node* p = createNode(n);
  17. p->next = top;
  18. top = p;
  19. }
  20. void Pop() {
  21. if (top == NULL) {
  22. return;
  23. }
  24. Node* temp = top;
  25. top = top->next;
  26. free(temp);
  27. }
  28. int Top() {
  29. if (top == NULL) {
  30. return;
  31. }
  32. return top->data;
  33. }
  34. void print() {
  35. printf("栈:");
  36. Node* temp = top;
  37. while (temp != NULL) {
  38. printf("%d", temp->data);
  39. temp = temp->next;
  40. }
  41. printf("\n");
  42. }
  43. int main(){
  44. Push(1);
  45. print();
  46. Push(2);
  47. print();
  48. Push(3);
  49. print();
  50. Push(4);
  51. print();
  52. Pop();
  53. print();
  54. printf("%d", Top());
  55. return 0;
  56. }

对于栈的主要实现细节:

在解释前,先说明栈这种数据结构有个特点,对于元素的添加、删除、返回栈顶元素,他们的实现都需要满足时间复杂度为O(1),其实就是他们的实现与元素的数量无关。

1.基于数组,对于一个数组,怎么去对应栈的各部分呢?

数组的添加在数组尾可以达到O(1),删除可以在数组头和数组尾进行达到O(1)。但是只有一边开口,所以只有数组尾满足条件,数组尾作为栈头。

1) push()函数(不考虑栈空间不足):直接对top+1(数组尾),这样就加入了一个元素。

2) pop()函数:如果栈中有元素(top != -1),直接top-1;

3) top()函数:直接返回数组尾,top就是栈顶元素的索引.

2.基于链表,对于一个链表呢?

链表的尾插需要O(n)的时间复杂度,所以我们直接选择头插法和头删法作为Push和Pop,同时也满足在O(1)下返回栈头元素。

1) push()函数(不考虑栈空间不足):直接头插法,无任何注意事项.

2) pop()函数:直接让top向后移动一位,这里注意:最后free掉的是原本top处的内存,而不是top指向的结点,所以需要有一个临时变量 = top,free(临时变量).

3) top()函数:如果有结点,直接返回head指向处数据.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/390511
推荐阅读
相关标签
  

闽ICP备14008679号