【无标题】【2025年软考中级】第三章数据结构3.2 栈与队列

文章目录

栈与队列



栈和队列是两种操作受限制的线性表数据结构,它们在计算机科学中应用广泛。理解它们的特性和实现原理是掌握数据结构的基础。

**LIFO(后进先出)**原则:最后进入的元素最先被移除

顺序栈

动态演示

顺序栈使用数组实现栈结构:

c 复制代码
typedef struct{ 
    Elemtype data[Maxsize]; 
    int top; // 栈顶指针
}SqStack;
核心操作
  • 栈空(初始化)s->top == -1
  • 栈满s->top == Maxsize-1
  • 进栈:指针先加1,再放入元素
  • 出栈:先取出元素,指针再减1

重要特性

  • 入栈出栈时间复杂度均为 O(1)

  • n个元素的合法出栈序列个数为卡特兰数
    C n = 1 n + 1 ( 2 n n ) C_n = \frac{1}{n+1}\binom{2n}{n} Cn=n+11(n2n)
    例如 n=4 时,有14种合法序列
    注意 :某些实现可能让栈空时 top==0,此时:

  • 入栈:先放入元素,指针再加1

  • 出栈:指针先减1,再取出元素

顺序共享栈

为节省空间,两个栈共享同一数组空间

c 复制代码
typedef struct{ 
    Elemtype data[Maxsize]; 
    int top1, top2; // top1从0开始,top2从Maxsize-1开始
}SqStack;
核心操作
  • 栈空
    • 栈1空:top1 == -1
    • 栈2空:top2 == Maxsize
  • 栈满top1 == top2 - 1
  • 进栈:先动指针,再放入元素
  • 出栈:先取出元素,再动指针

链栈

动态演示

使用链表实现的栈结构:

c 复制代码
typedef struct linknode{ 
    Elemtype data; 
    struct linknode *next; 
}LinkStNode;
核心操作
  • 栈空(初始化)s->next == NULL

  • 栈满:理论上不会栈满

  • 进栈:使用头插法添加新节点

  • 出栈 :取出头节点数据并删除节点

    c 复制代码
    p = head->next;
    e = p->data;
    head->next = p->next;
    free(p);

特点:栈底节点的 next 指针为 NULL

栈的应用

常见应用场景

  1. 括号匹配:检查表达式中的括号是否成对出现
  2. 表达式求值:将中缀表达式转换为后缀/前缀表达式
  3. 函数调用栈:实现递归调用和局部变量存储
  4. 进制转换:十进制转二进制/八进制/十六进制
  5. 迷宫求解:记录路径和回溯点

表达式求值详解

  • 前缀表达式(波兰式) :运算符在操作数之前 + 1 * 2 3
  • 中缀表达式 :运算符在操作数之间 1 + 2 * 3
  • 后缀表达式(逆波兰式) :运算符在操作数之后 1 2 3 * +

转换规则

  • 操作数相对位置不变

  • 运算符位置根据就近原则调整

  • 后缀表达式从左到右入栈计算

  • 前缀表达式从右到左入栈计算
    示例 :中缀 1+2*3 转换:

  • 前缀:+ 1 * 2 3

  • 后缀:1 2 3 * +

队列

**FIFO(先进先出)**原则:最先进入的元素最先被移除
尾进头出:入队操作在尾部,出队操作在头部

顺序队列

动态演示

c 复制代码
typedef struct{ 
    elemtype data[Maxsize]; 
    int rear, front; // 尾指针和头指针
}SqQueue;
核心操作
  • 初始化q->rear = q->front = -1
  • 队空q->front == q->rear
  • 队满q->rear == Maxsize-1
  • 入队++rear 后放入元素
  • 出队 :取出元素后 ++front

注意

  • front 总是指向队首元素的前一个位置
  • 含n个空间的队列最多执行n-1次入队操作
  • 入队出队时间复杂度均为 O(1)

循环队列

解决顺序队列的"假溢出"问题

c 复制代码
typedef struct{ 
    elemtype data[Maxsize]; 
    int rear, front;
}SqQueue;
核心操作
  • 初始化q->front = q->rear = 0
  • 队空q->rear == q->front
  • 队满(q->rear + 1) % Maxsize == q->front(浪费一个空间区分空/满)
  • 入队q->rear = (q->rear + 1) % Maxsize
  • 出队front = (front + 1) % Maxsize
关键计算
  • 元素个数count = (rear - front + Maxsize) % Maxsize
  • 队头位置front = (rear - count + Maxsize) % Maxsize
  • 队尾位置rear = (front + count) % Maxsize(仅当有减号时需加Maxsize)

链式队列

c 复制代码
typedef struct qnode{ 
    elemtype data; 
    struct qnode *next; 
}Datanode;

typedef struct{ 
    Datanode *front; 
    Datanode *rear; 
}Linkqunode;
核心操作
  • 初始化q->front = q->rear = NULL
  • 队空q->front == NULLq->rear == NULL
  • 入队:在尾部插入新节点(空队列需特殊处理)
  • 出队:删除头节点(只有一个节点需特殊处理)
  • 判断单节点q->front == q->rear != NULL

队列的应用

常见应用场景

  1. 缓冲区管理:操作系统中的I/O缓冲区
  2. CPU调度:进程就绪队列
  3. 打印队列:管理打印任务
  4. 广度优先搜索:图的层次遍历
  5. 页面替换算法:操作系统内存管理
  6. 迷宫求解:记录待探索的路径

栈与队列的区别

特性 队列
操作原则 LIFO(后进先出) FIFO(先进先出)
结构特点 仅需维护栈顶指针 需维护头尾双指针
入操作 先动指针,再放入元素 移动rear指针后放元素
出操作 先取元素,再动指针 移动front指针后取元素
典型应用 函数调用、表达式求值 任务调度、缓冲区管理
空间特性 顺序栈可能浪费空间 循环队列解决空间浪费
相关推荐
聆风吟º18 分钟前
【数据结构入门手札】数据结构基础:从数据到抽象数据类型
数据结构·数据类型·逻辑结构·数据对象·物理结构·数据项·数据元素
啊吧怪不啊吧20 分钟前
二分查找算法介绍及使用
数据结构·算法·leetcode
立志成为大牛的小牛2 小时前
数据结构——四十二、二叉排序树(王道408)
数据结构·笔记·程序人生·考研·算法
摇滚侠9 小时前
StreamAPI,取出list中的name属性,返回一个新list
数据结构·list
是苏浙13 小时前
零基础入门C语言之C语言实现数据结构之单链表经典算法
c语言·开发语言·数据结构·算法
橘颂TA13 小时前
【剑斩OFFER】算法的暴力美学——点名
数据结构·算法·leetcode·c/c++
迷途之人不知返14 小时前
数据结构之,栈与队列
数据结构
MOONICK16 小时前
数据结构——哈希表
数据结构·哈希算法·散列表
FMRbpm18 小时前
链表5--------删除
数据结构·c++·算法·链表·新手入门
努力学习的小全全19 小时前
【CCF-CSP】05-01数列分段
数据结构·算法·ccf-csp