数据结构的重要部分,栈,栈是OI中常用的一种线性数据结构,请注意,本文主要讲的是栈这种数据结构,而非程序运行时的系统栈/栈空间,大家一定要弄清晰,别混淆了。


栈的定义和特点

栈(stack)是一个特殊的线性表,是限定仅在一端(通常是表尾)进行插入和删除操作的线性表。又称为后进先出(Last In First Out)的线性表,简称 LIFO 结构。

栈1

栈2

栈的特点:后进先出,先进者后出,就像我们在放盘子,使用的时候先用后放的,后使用先放的。从栈的操作特性上来看,栈是一种“操作受限”的线性表,只允许在一端插入和删除数据。


栈的相关概念:栈是仅在表尾进行插入、删除操作的线性表。

表尾(即an端)称为栈顶 Top;表头(即a1端)称为栈底 Base

例如:栈 s = (a1,a2,a3.....an-1,an)  a1被称为栈底元素,an被称为栈顶元素

插入元素到栈顶(即表尾)的操作,称为入栈。

从栈顶(即表尾)删除最后一个元素的操作,称为出栈。

栈的示意图:

栈的示意图

操作示意图-入栈:

操作示意图-入栈

操作示意图-出栈:

操作示意图-出栈


当某个数据集合只涉及在一端插入和删除数据,并且满足先进后出、后进先出的特性,应该首选“栈”这种数据结构。栈的操作包含两个操作:入栈和出栈

栈既可以用数组实现,也可以用链表来实现。用数组实现的栈叫顺序栈,用链表实现的栈叫链式栈。

对于出栈操作,不会涉及到内存的重新申请和数据的搬移,所以出栈的时间复杂度仍然是O(1)。对于入栈的操作,如果栈中有空闲空间时,入栈的操作时间复杂度是O(1),当空间不够时,就需要重新申请内存和数据搬移,所以时间复杂度就变成了O(n)。从上述可以看出,入栈的最好情况时间复杂度为O(1),最坏情况时间复杂度为O(n)。

入栈的时间复杂度如下图所示:

入栈的时间复杂度


栈在函数调用中的应用

栈作为一个比较基础的数据结构,应用场景还是蛮多的。其中,比较经典的一个应用场景就是函数调用栈。

每进入一个函数,就会将临时变量作为一个栈帧入栈,当被调用函数执行完成,返回之后,将这个函数对应的栈帧出栈。例如下面的这个例子:

int main() {
   int a = 1; 
   int ret = 0;
   int res = 0;
   ret = add(3, 5);
   res = a + ret;
   printf("%d", res);
   reuturn 0;
}

int add(int x, int y) {
   int sum = 0;
   sum = x + y;
   return sum;
}

这个例子调用栈的分析如下图所示:

调用栈的分析

我们平时使用的浏览器大家肯定不陌生,浏览器中的前进和后退其实就是栈的使用,在访问一个网页时可以理解为入栈操作,返回上一个页面可以理解为出栈操作。


点赞(0)

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

Dotcpp在线编译      (登录可减少运行等待时间)