一、什么是栈?

在我们软件应用中,栈这种后进先出数据结构的应用是非常普遍的。比如 Word、 Photoshop 等文档或图像编辑软件中, 都有撤销(undo)的操作,也是用栈这种方式来实现的。

栈(stack)是限定仅在表尾进行插入和删除操作的线性表。

我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈。 栈又称为后进先出(Last In Filrst Out) 的线性表,简称 LlFO 结构。

栈的插入操作,叫作进栈,也称压栈、入栈。类似子弹入弹夹,如下图-左所示。栈的删除操作,叫作出栈,也有的叫作弹栈。

二、什么是顺序栈?

顺序栈:是指利用顺序存储结构实现的栈。线性栈可以用数组来实现,对于栈这种只能一头插入删除的线性表来说,用数组哪一端来作为栈顶和栈底比较好?

对,没错,下标为 0 的一端作为栈底比较好,因为首元素都存在栈底,变化最小,所以让它作栈底。我们定义一个 top 变量来指示栈顶元素在数组中的位置,若存储栈的长度为 StackSize,则栈顶位置 top 必须小于 StackSize。当栈存在一个元素时,top 等于 0,因此通常把空栈的判定条件定为 top 等于 -1。

来看栈的结构定义:

  1. typedef int ElemType; /* ElemType类型根据实际情况而定,这里假设为int */
  2. /* 顺序栈结构 */
  3. typedef struct
  4. {
  5. ElemType data[MAXSIZE];
  6. int top; /* 用于栈顶指针 */
  7. }SeqStack;

若现在有一个栈,StackSize 是 5,则栈普通情况、空栈和栈满的情况示意图如下图所示:

  • 栈空时:栈顶指针(top)= -1;
  • 栈满时:栈顶指针(top)= MAXSIZE-1;
  • 栈未满:就是栈中存在元素,top 指针还未达到 MAXSIZE-1。

三、基本操作

3.1 初始化栈操作

实现代码如下:

  1. // 初始化栈操作
  2. Status initStack(SeqStack **stack)
  3. {
  4. *stack = (SeqStack *)malloc(sizeof(SeqStack));
  5. (*stack)->top = -1;
  6. return TRUE;
  7. }

3.2 进栈操作

进栈的示意图如下:

实现进栈只需要两步:

  • 判断栈是否已经满了,如果满了当然就入不了栈。
  • 栈顶指针 +1,在新栈顶位置存入要进栈的元素。

实现代码如下:

  1. // 进栈操作
  2. Status push(SeqStack *stack, const ElemType e)
  3. {
  4. if (stack->top == MAXSIZE - 1) // 判断是否栈满
  5. {
  6. return FALSE;
  7. }
  8. stack->top++; // 栈顶指针加1
  9. stack->data[stack->top] = e; // 将新插入元素赋值给栈顶空间
  10. return TRUE;
  11. }

3.3 出栈操作

出栈的示意图如下:

实现出栈也只需要两步:

  • 判断栈是否为空,里面没有数据先出栈也没有。
  • 将栈顶元素出栈,栈顶指针 -1。

实现代码如下:

  1. // 出栈操作
  2. Status pop(SeqStack *stack, ElemType *e)
  3. {
  4. if (stack->top == -1) // 判断是否空栈
  5. return FALSE;
  6. *e = stack->data[stack->top]; // 将要删除的栈顶元素赋值给e
  7. stack->top--; // 栈顶指针减1
  8. return TRUE;
  9. }

3.4 遍历栈操作

实现代码如下:

  1. // 遍历栈操作
  2. Status traverseStack(SeqStack *stack)
  3. {
  4. for (int i = 0; i <= stack->top; i++)
  5. printf("%d ", stack->data[i]);
  6. printf("\n");
  7. return TRUE;
  8. }

四、完整程序

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define TRUE 1
  4. #define FALSE 0
  5. #define MAXSIZE 20 /* 存储空间初始分配量 */
  6. typedef int Status;
  7. typedef int ElemType; /* ElemType类型根据实际情况而定,这里假设为int */
  8. /* 顺序栈结构 */
  9. typedef struct
  10. {
  11. ElemType data[MAXSIZE];
  12. int top; /* 用于栈顶指针 */
  13. }SeqStack;
  14. Status initStack(SeqStack **stack); // 初始化栈操作
  15. Status push(SeqStack *stack, const ElemType e); // 进栈操作
  16. Status pop(SeqStack *stack, ElemType *e); // 出栈操作
  17. Status traverseStack(SeqStack *stack); // 遍历栈操作
  18. Status clearStack(SeqStack *stack); // 清空栈操作
  19. Status isEmpty(SeqStack *stack); // 判断是否为空
  20. Status getTop(SeqStack *stack, ElemType *e); // 获得栈顶元素
  21. int getLength(SeqStack *stack); // 获取栈的长度
  22. // 初始化栈操作
  23. Status initStack(SeqStack **stack)
  24. {
  25. *stack = (SeqStack *)malloc(sizeof(SeqStack));
  26. (*stack)->top = -1;
  27. return TRUE;
  28. }
  29. // 进栈操作
  30. Status push(SeqStack *stack, const ElemType e)
  31. {
  32. if (stack->top == MAXSIZE - 1) // 判断是否栈满
  33. {
  34. return FALSE;
  35. }
  36. stack->top++; // 栈顶指针加1
  37. stack->data[stack->top] = e; // 将新插入元素赋值给栈顶空间
  38. return TRUE;
  39. }
  40. // 出栈操作
  41. Status pop(SeqStack *stack, ElemType *e)
  42. {
  43. if (stack->top == -1) // 判断是否空栈
  44. return FALSE;
  45. *e = stack->data[stack->top]; // 将要删除的栈顶元素赋值给e
  46. stack->top--; // 栈顶指针减1
  47. return TRUE;
  48. }
  49. // 遍历栈操作
  50. Status traverseStack(SeqStack *stack)
  51. {
  52. for (int i = 0; i <= stack->top; i++)
  53. printf("%d ", stack->data[i]);
  54. printf("\n");
  55. return TRUE;
  56. }
  57. // 清空栈操作
  58. Status clearStack(SeqStack *stack)
  59. {
  60. stack->top = -1;
  61. return TRUE;
  62. }
  63. // 判断是否为空
  64. Status isEmpty(SeqStack *stack)
  65. {
  66. return stack->top == -1 ? TRUE : FALSE;
  67. }
  68. // 获得栈顶元素
  69. Status getTop(SeqStack *stack, ElemType *e)
  70. {
  71. if (stack->top == -1)
  72. return FALSE;
  73. else
  74. *e = stack->data[stack->top];
  75. return TRUE;
  76. }
  77. // 获取栈的长度
  78. int getLength(SeqStack *stack)
  79. {
  80. return stack->top + 1;
  81. }
  82. int main()
  83. {
  84. // 初始化栈
  85. SeqStack *stack;
  86. if (initStack(&stack) == TRUE)
  87. printf("初始化顺序栈成功!\n\n");
  88. // 入栈操作
  89. for (int j = 1; j <= 10; j++)
  90. push(stack, j);
  91. printf("入栈操作(0-10)!\n\n");
  92. // 出栈操作
  93. int e;
  94. pop(stack, &e);
  95. printf("弹出的栈顶元素e=%d\n\n", e);
  96. // 遍历栈
  97. printf("遍历栈,栈中元素依次为:");
  98. traverseStack(stack);
  99. printf("\n");
  100. // 获得栈顶元素
  101. getTop(stack, &e);
  102. printf("栈顶元素 e=%d 栈的长度为%d\n\n", e, getLength(stack));
  103. // 判断是否为空栈
  104. printf("栈空否:%d(1:空 0:否)\n\n", isEmpty(stack));
  105. // 清空栈
  106. clearStack(stack);
  107. printf("清空栈后,栈空否:%d(1:空 0:否)\n\n", isEmpty(stack));
  108. return 0;
  109. }

输出结果如下图所示:

参考:

《大话数据结构 - 第4章》 栈与队列

数据结构 - 顺序栈的实行(C语言)的更多相关文章

  1. 数据结构 - 链栈的实行(C语言)

    数据结构-链栈的实现 1 链栈的定义 现在来看看栈的链式存储结构,简称为链栈. 想想看栈只是栈顶来做插入和删除操作,栈顶放在链表的头部还是尾部呢?由于单链表有头指针,而栈顶指针也是必须的,那干吗不让它 ...

  2. 顺序栈的基本操作(C语言)

    由于现在只学了C语言所以就写这个C语言版的栈的基本操作 这里说一下 :网上和书上都有这种写法 int InitStack(SqStack &p) &p是取地址  但是这种用法好像C并不 ...

  3. 数据结构 - 顺序栈的实现 C++

    顺序栈封装 C++ 使用C++对顺序栈进行了简单的封装,实现了栈的基本操作 封装方法: pop(),top(),size(),empty(),push() 代码已经过测试 #pragma once # ...

  4. 数据结构 - 顺序队列的实行(C语言)

    数据结构-顺序队列的实现 1 顺序队列的定义 线性表有顺序存储和链式存储,队列作为一种特殊的线性表,也同样存在这两种存储方式.我们先来看队列的顺序存储结构. 队列的顺序储存结构:用数组存储队列,为了避 ...

  5. 数据结构——顺序栈(sequence stack)

    /* sequenceStack.c */ /* 栈 先进后出(First In Last Out,FILO)*/ #include <stdio.h> #include <stdl ...

  6. 数据结构--顺序栈--C++实现

    #include <iostream> #define MaxSize 5000 using namespace std; template <typename T> clas ...

  7. C++语言实现顺序栈

    C++语言实现顺序栈 在写C语言实现顺序栈的时候,我已经向大家介绍了栈的特点以及介绍了栈的相关操作,并利用C语言实现了相关算法.在这里小编就不在继续给大家介绍了,需要温习的可以去我的博客看看.在这篇博 ...

  8. 【C#】【数据结构】005-栈:顺序栈

    C#数据结构:顺序栈 1.自定义顺序栈结构: /// <summary> /// 顺序栈 /// </summary> /// <typeparam name=" ...

  9. 数据结构与算法之顺序栈C语言实现

    顺序栈是一种特殊的顺序表,主要操作是入栈和出栈.将顺序表加一些特定限制,就成了顺序栈. 注: 1.顺序栈C语言实现: 2.按较简单的方式实现,主要帮助理解,可在此基础上修改,更加完善: 3.提供几个简 ...

随机推荐

  1. 【Nginx】http模块的数据结构

    定义fttp模块方式很简单,比如:ngx_module_t ngx_http_mytest_module; 其中,ngx_module_t是一个Nginx模块的数据结构. typedef struct ...

  2. [Angular] Modify User Provided UI with Angular Content Directives

    If we’re going to make our toggle accessible, we’ll need to apply certain aria attributes to the con ...

  3. POJ 1988 Cube Stacking(并查集+路径压缩)

    题目链接:id=1988">POJ 1988 Cube Stacking 并查集的题目 [题目大意] 有n个元素,開始每一个元素自己 一栈.有两种操作,将含有元素x的栈放在含有y的栈的 ...

  4. ES文件浏览器 WIFI 查看电脑文件怎么弄

    1 开启来宾账户   2 右击要共享的文件夹,添加Guest共享(如果只是要查看共享的资源,权限级别为读取即可)   3 共享之后,网络路径就是"\\"+你的计算机名+" ...

  5. hdoj 2046 骨牌铺方格 【DP】+【斐波那契】

    dp果然不是好学的... 第n个,即2*n时,可由第n-1个的竖直排列再加一个,和第n-2个中横着排两个 所以f(n) = 1×f(n-1) + 1×f(n-2): 骨牌铺方格 Time Limit: ...

  6. I2C上拉电阻取值范围

    I2C总线是微电子通信控制领域中常用的一种总线标准,具备接线少,控制简单,速率高等优点.在I2C电路中常见的上拉电阻有1k.1.5k.2.2k.4.7k.5.1k.10k等等,但是应该如何根据开发要求 ...

  7. 挖掘更合适的MVP模式的架构设计

        关于MVP,关于android,不得不说这篇博客已经来的非常晚了,这篇博客早就想写了,一直都在偷懒,就不给自己这么久的偷懒找借口了.尽管这篇文章po出来的比較晚.可是我所接触的程序猿一些朋友之 ...

  8. Android多线程更新UI的方式

    Android下,对于耗时的操作要放到子线程中,要不然会残生ANR,本次我们就来学习一下Android多线程更新UI的方式. 首先我们来认识一下anr: anr:application not rep ...

  9. POJ 1125 Stockbroker Grapevine (Floyd最短路)

    Floyd算法计算每对顶点之间的最短路径的问题 题目中隐含了一个条件是一个人能够同一时候将谣言传递给多个人 题目终于的要求是时间最短.那么就要遍历一遍求出每一个点作为源点时,最长的最短路径长是多少,再 ...

  10. myecplise、ecplise项目空间优化

    1.代码自动提示补全 Window->preferences->Java->Editor->Content Assist 再右下角Auto activation trigger ...