1.栈:后进先出的线性数据结构

一、什么是栈?

栈(Stack)是一种后进先出(LIFO, Last In First Out)的线性数据结构,它只允许在一端进行插入和删除操作,这一端被称为栈顶(top) ,另一端则称为栈底(base)

简单来说,栈就像一个 "一端封闭的容器":

  • 最后放入的元素,会最先被取出;
  • 最先放入的元素,会最后被取出。

二、栈的核心结构

视频中提到,栈的本质是一段连续内存 + 一个栈顶指针

  • 连续内存:用于存储栈中的元素,通常用数组实现;
  • 栈顶指针(top):指向栈顶元素的位置,初始值为 -1,表示栈为空。

对应的 C 语言代码定义如下:

复制代码
#define MAX_SIZE 100  // 栈的最大容量

// 栈的结构体定义
typedef struct {
    int data[MAX_SIZE];  // 连续内存,存储栈元素
    int top;             // 栈顶指针,-1表示空栈
} Stack;

三、栈的基本操作

栈的核心操作有两个:入栈(Push)出栈(Pop) ,这两个操作的时间复杂度都是 O(1)(常数时间),因为它们不需要遍历整个栈,只需要操作栈顶指针。

1. 入栈(Push):压入栈顶

入栈操作是将元素添加到栈顶,步骤如下:

  1. 判满 :如果栈顶指针等于 MAX_SIZE - 1,说明栈已满,无法再添加元素;
  2. 先自增,再写入:将栈顶指针加 1,然后将元素写入到新的栈顶位置。

代码实现:

复制代码
// 入栈操作
void push(Stack *s, int value) {
    // 判满:栈顶指针到达最大容量的前一个位置
    if (s->top == MAX_SIZE - 1) {
        printf("栈已满,无法入栈!\n");
        return;
    }
    // 先自增栈顶指针,再写入元素
    s->data[++s->top] = value;
}

2. 出栈(Pop):弹出栈顶

出栈操作是将栈顶元素取出,步骤如下:

  1. 判空 :如果栈顶指针等于 -1,说明栈为空,无法再取出元素;
  2. 先读取,再自减:先读取栈顶元素,然后将栈顶指针减 1。

代码实现:

复制代码
// 出栈操作
int pop(Stack *s) {
    // 判空:栈顶指针为-1表示空栈
    if (s->top == -1) {
        printf("栈为空,无法出栈!\n");
        return -1;  // 用-1表示错误,实际应用中可自定义错误码
    }
    // 先读取栈顶元素,再自减栈顶指针
    return s->data[s->top--];
}

四、栈的初始化与建立

在使用栈之前,需要先初始化栈,将栈顶指针设置为 -1,表示栈为空。

代码实现:

复制代码
// 初始化栈
void initStack(Stack *s) {
    s->top = -1;  // 栈顶指针归位到-1,表示空栈
}

建立栈的过程就是逐个将元素入栈的过程:

复制代码
int main() {
    Stack s;
    initStack(&s);  // 初始化栈

    // 逐个入栈,建立栈
    push(&s, 10);
    push(&s, 20);
    push(&s, 30);

    // 出栈测试
    printf("出栈元素:%d\n", pop(&s));  // 输出30(后进先出)
    printf("出栈元素:%d\n", pop(&s));  // 输出20
    printf("出栈元素:%d\n", pop(&s));  // 输出10

    return 0;
}

五、栈溢出(Stack Overflow)

栈的容量是有限的,当入栈的元素超过栈的最大容量时,就会发生栈溢出

视频中提到,当栈顶指针越过 MAX_SIZE - 1 时,栈空间就耗尽了,此时入栈操作会失败。

避免栈溢出的方法:

  1. 合理设置栈的最大容量 MAX_SIZE
  2. 在入栈前先判断栈是否已满。

六、总结

栈是一种非常基础且重要的数据结构,它的核心特点是后进先出 ,通过连续内存 + 栈顶指针 实现,基本操作的时间复杂度为 O(1)

在实际应用中,栈常用于:

  • 函数调用栈(保存函数的返回地址和局部变量);
  • 表达式求值(如后缀表达式计算);
  • 括号匹配问题;
  • 深度优先搜索(DFS)等。

希望这篇文章能帮助你理解栈的原理和实现!

相关推荐
aramae6 小时前
MySQL复合查询(8)
java·c语言·开发语言·后端·算法
无敌贵点大王7 小时前
RTThread学习记录11——RT-Thread 设备模型吃透:UART/ADC/PWM/PIN 到底有什么区别?
c语言·stm32·学习·链表
淡海水7 小时前
13-04-面试-源码级深度追问链
数据结构·unity·面试·c#·游戏引擎·源码·il2cpp
Logic1017 小时前
C语言/数据结构位运算题解:异或XOR找出时尚聚会中的“独特颜色“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
崇山峻岭之间10 小时前
HC32F460PETB的PB2的Vout123
单片机
恶魔泡泡糖10 小时前
stm32F103C8T6标准库串口接收之中断方式2
stm32·单片机·嵌入式硬件
充哥单片机设计10 小时前
【STM32开源项目】智能小区充电桩
stm32·单片机·嵌入式硬件·毕业设计·小区充电桩·智能小区充电桩
2401_8390805411 小时前
C++常见八股
数据结构·c++·算法
嵌入式-老费11 小时前
esp32开发与应用(如何解决SoC冷启动的问题)
单片机·嵌入式硬件
暮雨封夕11 小时前
跳表(Skip List)详解:原理、实现、使用场景与实际应用
数据结构