栈——栈的定义及基本操作

一、什么是栈?

在学习数据结构时, 是一种非常重要、也非常基础的线性结构。

栈的英文是 Stack,它是一种特殊的线性表。和普通线性表不同的是,栈只允许在一端进行插入和删除操作。

这个允许插入和删除的一端,称为 栈顶 ;另一端称为 栈底

栈最大的特点是:

后进先出

也就是:

Last In First Out,简称 LIFO

举一个生活中的例子:

我们把一摞盘子一个一个叠起来,最先放进去的盘子在最下面,最后放上去的盘子在最上面。当我们取盘子时,通常也是先取最上面的那个。

这就是一个典型的栈结构。


二、栈的基本特点

栈是一种受限制的线性表,它具有以下特点:

  1. 只能在栈顶进行插入和删除操作。

  2. 插入操作称为 入栈压栈

  3. 删除操作称为 出栈

  4. 最后入栈的元素,会最先出栈。

  5. 最先入栈的元素,会最后出栈。

例如依次将元素:

复制代码
1 2 3

入栈,那么栈中的结构可以理解为:

复制代码
栈顶 -> 3
        2
栈底 -> 1

此时如果进行出栈操作,最先被删除的是元素 3,然后是 2,最后才是 1


三、栈的基本操作

栈常见的基本操作有以下几种:

操作名称 英文名称 含义
入栈 push 向栈顶插入一个元素
出栈 pop 删除栈顶元素
取栈顶元素 top / peek 获取当前栈顶元素
判断栈是否为空 empty 判断栈中是否没有元素
获取栈中元素个数 size 返回栈中元素数量

下面分别进行介绍。


四、入栈操作 push

入栈就是将一个新元素放到栈顶。

假设原来的栈是:

复制代码
栈顶 -> 2
栈底 -> 1

现在执行:

复制代码
push(3);

入栈之后变成:

复制代码
栈顶 -> 3
        2
栈底 -> 1

可以看到,新元素 3 被放到了栈顶。

在 C++ STL 中,入栈操作使用:

复制代码
st.push(x);

示例代码:

复制代码
#include <iostream>
#include <stack>
using namespace std;

int main() {
    stack<int> st;

    st.push(1);
    st.push(2);
    st.push(3);

    cout << "元素入栈完成" << endl;

    return 0;
}

五、出栈操作 pop

出栈就是删除当前栈顶元素。

假设当前栈为:

复制代码
栈顶 -> 3
        2
栈底 -> 1

执行一次出栈操作:

复制代码
pop();

出栈之后变成:

复制代码
栈顶 -> 2
栈底 -> 1

原来的栈顶元素 3 被删除。

在 C++ STL 中,出栈操作使用:

复制代码
st.pop();

需要注意的是:

pop() 只负责删除栈顶元素,不会返回被删除的元素。

如果想要获取栈顶元素,需要先使用 top(),然后再使用 pop()

示例代码:

复制代码
#include <iostream>
#include <stack>
using namespace std;

int main() {
    stack<int> st;

    st.push(1);
    st.push(2);
    st.push(3);

    cout << "当前栈顶元素是:" << st.top() << endl;

    st.pop();

    cout << "出栈后,新的栈顶元素是:" << st.top() << endl;

    return 0;
}

运行结果:

复制代码
当前栈顶元素是:3
出栈后,新的栈顶元素是:2

六、获取栈顶元素 top

栈顶元素就是最后一个入栈、并且还没有被删除的元素。

在 C++ STL 中,可以使用:

复制代码
st.top();

来获取栈顶元素。

示例代码:

复制代码
#include <iostream>
#include <stack>
using namespace std;

int main() {
    stack<int> st;

    st.push(10);
    st.push(20);
    st.push(30);

    cout << "栈顶元素是:" << st.top() << endl;

    return 0;
}

运行结果:

复制代码
栈顶元素是:30

需要注意的是:

在使用 top() 之前,最好先判断栈是否为空。

如果栈为空,直接调用 top() 会导致程序出现错误。


七、判断栈是否为空 empty

判断栈是否为空,可以使用:

复制代码
st.empty();

如果栈为空,返回 true;否则返回 false

示例代码:

复制代码
#include <iostream>
#include <stack>
using namespace std;

int main() {
    stack<int> st;

    if (st.empty()) {
        cout << "当前栈为空" << endl;
    } else {
        cout << "当前栈不为空" << endl;
    }

    st.push(100);

    if (st.empty()) {
        cout << "当前栈为空" << endl;
    } else {
        cout << "当前栈不为空" << endl;
    }

    return 0;
}

运行结果:

复制代码
当前栈为空
当前栈不为空

八、获取栈的元素个数 size

获取栈中元素的数量,可以使用:

复制代码
st.size();

示例代码:

复制代码
#include <iostream>
#include <stack>
using namespace std;

int main() {
    stack<int> st;

    st.push(1);
    st.push(2);
    st.push(3);

    cout << "当前栈中元素个数为:" << st.size() << endl;

    return 0;
}

运行结果:

复制代码
当前栈中元素个数为:3

九、完整示例:栈的基本操作演示

下面通过一个完整程序,演示栈的入栈、出栈、获取栈顶元素、判断是否为空等操作。

复制代码
#include <iostream>
#include <stack>
using namespace std;

int main() {
    stack<int> st;

    // 入栈操作
    st.push(10);
    st.push(20);
    st.push(30);

    cout << "当前栈中元素个数:" << st.size() << endl;
    cout << "当前栈顶元素:" << st.top() << endl;

    // 出栈操作
    st.pop();

    cout << "执行一次出栈后:" << endl;
    cout << "当前栈中元素个数:" << st.size() << endl;
    cout << "当前栈顶元素:" << st.top() << endl;

    // 继续出栈
    st.pop();
    st.pop();

    if (st.empty()) {
        cout << "栈已经为空" << endl;
    } else {
        cout << "栈不为空" << endl;
    }

    return 0;
}

运行结果:

复制代码
当前栈中元素个数:3
当前栈顶元素:30
执行一次出栈后:
当前栈中元素个数:2
当前栈顶元素:20
栈已经为空

十、用数组模拟栈

除了使用 C++ STL 中的 stack,我们也可以使用数组手动模拟栈。

数组模拟栈的核心思想是:

使用一个变量 top 表示栈顶位置。

初始时:

复制代码
top = -1;

表示栈为空。

每次入栈时,先让 top 加一,然后把元素放到 top 位置。

每次出栈时,只需要让 top 减一即可。

示例代码:

复制代码
#include <iostream>
using namespace std;

const int MAXN = 100;

int st[MAXN];
int topIndex = -1;

// 入栈
void push(int x) {
    if (topIndex == MAXN - 1) {
        cout << "栈已满,无法入栈" << endl;
        return;
    }

    st[++topIndex] = x;
}

// 出栈
void pop() {
    if (topIndex == -1) {
        cout << "栈为空,无法出栈" << endl;
        return;
    }

    topIndex--;
}

// 获取栈顶元素
int top() {
    if (topIndex == -1) {
        cout << "栈为空,没有栈顶元素" << endl;
        return -1;
    }

    return st[topIndex];
}

// 判断栈是否为空
bool empty() {
    return topIndex == -1;
}

// 获取栈中元素个数
int size() {
    return topIndex + 1;
}

int main() {
    push(10);
    push(20);
    push(30);

    cout << "栈顶元素:" << top() << endl;
    cout << "栈中元素个数:" << size() << endl;

    pop();

    cout << "出栈后栈顶元素:" << top() << endl;

    return 0;
}

运行结果:

复制代码
栈顶元素:30
栈中元素个数:3
出栈后栈顶元素:20

十一、栈的常见应用

栈虽然结构简单,但是应用非常广泛。

常见应用包括:

1. 函数调用

程序在调用函数时,会使用调用栈保存函数的执行状态。

例如函数 A 调用函数 B,函数 B 又调用函数 C,那么函数 C 执行完后,会先返回到函数 B,再返回到函数 A。

这正好符合栈的 后进先出 特点。


2. 表达式求值

在计算数学表达式时,栈经常用于处理中缀表达式、后缀表达式等问题。

例如:

复制代码
3 + 5 * 2

计算时需要考虑运算符优先级,栈可以帮助我们保存数字和运算符。


3. 括号匹配

判断括号是否合法,是栈的经典应用。

例如:

复制代码
()[]{} 

是合法的。

而:

复制代码
([)]

是不合法的。

判断括号匹配时,可以遇到左括号就入栈,遇到右括号就和栈顶元素进行匹配。


4. 深度优先搜索 DFS

在图和树的遍历中,深度优先搜索可以使用栈来实现。

递归本质上也可以理解为系统自动维护了一个栈。


5. 浏览器前进后退

浏览器的后退功能也可以用栈来理解。

用户访问过的页面会依次保存,当点击后退时,会回到最近访问的上一个页面。


十二、使用栈时的注意事项

在使用栈时,需要注意以下几点:

1. 空栈不能直接取栈顶元素

错误写法:

复制代码
cout << st.top() << endl;

如果此时栈为空,程序可能会出错。

推荐写法:

复制代码
if (!st.empty()) {
    cout << st.top() << endl;
}

2. 空栈不能直接出栈

错误写法:

复制代码
st.pop();

如果栈为空,直接出栈也可能导致程序错误。

推荐写法:

复制代码
if (!st.empty()) {
    st.pop();
}

3. pop() 不会返回栈顶元素

很多初学者容易写出这样的代码:

复制代码
int x = st.pop();

这是错误的。

因为 pop() 的作用只是删除栈顶元素,并不会返回元素。

正确写法应该是:

复制代码
int x = st.top();
st.pop();

十三、总结

栈是一种非常基础但非常重要的数据结构。

它的核心特点是:

复制代码
后进先出 LIFO

栈只允许在一端进行插入和删除操作,这一端称为栈顶。

栈的基本操作包括:

复制代码
push()   // 入栈
pop()    // 出栈
top()    // 获取栈顶元素
empty()  // 判断是否为空
size()   // 获取元素个数

在实际开发和算法题中,栈经常用于括号匹配、表达式求值、函数调用、DFS 遍历等场景。

虽然栈的结构并不复杂,但它是学习后续数据结构与算法的重要基础。掌握栈的定义和基本操作,对于理解递归、搜索、表达式处理等内容都有很大帮助。

相关推荐
不想写代码的星星1 小时前
C++ 内存序六件套:从完全同步到爱咋咋地
c++
取经蜗牛1 小时前
Windows 11 WSL + Ubuntu 24.04 安装指南
linux·windows·ubuntu
ゆづき2 小时前
Java 初学者入门指南:常见问题 + 核心知识点 + 进阶 20 道练习题
java·开发语言·学习·算法·水题
大树学长2 小时前
【QT开发】Windows 10 + Qt 5.15.2 手动编译安装 Qt OPC UA 模块完整记录
开发语言·windows·qt
Evand J2 小时前
【课题推荐】强跟踪UKF算法,三维非线性状态量和观测量,附MATLAB代码测试结果
开发语言·算法·matlab
idolao2 小时前
Autodesk VRED Professional 2025安装教程 Windows版:自定义路径+Keygen指南
windows
haibindev3 小时前
别让AI再从零写一堆优美的屎山了
c++·ai编程·claude·流媒体·codex·代码复用
Zhang~Ling3 小时前
C++ 模板初阶:从函数模板到类模板
c++