STL 栈 队列

C++ STL 栈、队列与优先级队列:从入门到模拟实现

栈(stack)、队列(queue)、优先级队列(priority_queue)是 C++ STL 中非常经典的容器适配器,它们不直接存储数据,而是封装底层容器实现特定数据结构规则。本文从基础用法、经典场景到模拟实现,一次性讲透这三个核心组件。

一、栈(stack):后进先出的线性结构

1.1 栈的核心特性

栈遵循后进先出(LIFO) 原则,仅允许在栈顶进行插入、删除、访问操作,不支持遍历与中间位置操作。

1.2 栈的常用接口

函数 功能
stack() 构造空栈
empty() 判断栈是否为空
size() 返回栈中元素个数
top() 返回栈顶元素引用
push(val) 元素入栈(栈顶)
pop() 栈顶元素出栈

1.3 最小栈(经典扩展)

最小栈支持在 O(1) 时间内获取栈中最小值,核心思路是用两个栈:一个存原始数据,一个存最小值。

cpp 复制代码
class MinStack {
public:
    void push(int x) {
        _elem.push(x);
        if (_min.empty() || x <= _min.top()) {
            _min.push(x);
        }
    }

    void pop() {
        if (_min.top() == _elem.top()) {
            _min.pop();
        }
        _elem.pop();
    }

    int top() { return _elem.top(); }
    int getMin() { return _min.top(); }

private:
    std::stack<int> _elem;  // 存储原始数据
    std::stack<int> _min;   // 存储最小值
};

1.4 栈的模拟实现

栈仅需尾插、尾删操作,底层可封装 vector/deque/list,默认用 deque。

cpp 复制代码
#include <vector>
namespace man{
template<class T>
class stack {
public:
    stack() {}
    void push(const T& x) { _c.push_back(x); }
    void pop() { _c.pop_back(); }
    T& top() { return _c.back(); }
    const T& top() const { return _c.back(); }
    size_t size() const { return _c.size(); }
    bool empty() const { return _c.empty(); }

private:
    std::vector<T> _c;
};
}

二、队列(queue):先进先出的线性结构

2.1 队列的核心特性

队列遵循先进先出(FIFO) 原则,队尾入队、队头出队,同样不支持遍历与中间操作。

2.2 队列的常用接口

函数 功能
queue() 构造空队列
empty() 判断队列是否为空
size() 返回队列有效元素个数
front() 返回队头元素引用
back() 返回队尾元素引用
push(val) 队尾入队
pop() 队头出队

2.3 队列的模拟实现

队列需要尾插、头删,vector 头删效率低,推荐封装 list/deque

cpp 复制代码
#include <list>
namespace man {
template<class T>
class queue {
public:
    queue() {}
    void push(const T& x) { _c.push_back(x); }
    void pop() { _c.pop_front(); }
    T& back() { return _c.back(); }
    const T& back() const { return _c.back(); }
    T& front() { return _c.front(); }
    const T& front() const { return _c.front(); }
    size_t size() const { return _c.size(); }
    bool empty() const { return _c.empty(); }

private:
    std::list<T> _c;
};
}

三、优先级队列(priority_queue):堆的封装

3.1 优先级队列核心特性

优先级队列本质是 ,默认是大顶堆(堆顶为最大值),支持快速获取极值,插入/删除均为 O(logN) 复杂度。

3.2 优先级队列常用接口

函数 功能
priority_queue() 构造空优先级队列
empty() 判断是否为空
top() 返回堆顶元素(最大/最小值)
push(val) 插入元素并调整堆
pop() 删除堆顶元素并调整堆

3.3 大堆与小堆创建

cpp 复制代码
#include <vector>
#include <queue>
#include <functional>

void TestPriorityQueue() {
    vector<int> v{3,2,7,6,0,4,1,9,8,5};
    // 默认大顶堆
    priority_queue<int> q1(v.begin(), v.end());
    // 小顶堆(第三个参数为 greater)
    priority_queue<int, vector<int>, greater<int>> q2(v.begin(), v.end());
}

3.4 自定义类型适配

自定义类型需要重载 <> 运算符,才能用于优先级队列。

cpp 复制代码
class Date {
public:
    Date(int year = 1900, int month = 1, int day = 1)
        : _year(year), _month(month), _day(day) {}

    bool operator<(const Date& d) const {
        return (_year < d._year) ||
               (_year == d._year && _month < d._month) ||
               (_year == d._year && _month == d._month && _day < d._day);
    }

    bool operator>(const Date& d) const {
        return (_year > d._year) ||
               (_year == d._year && _month > d._month) ||
               (_year == d._year && _month == d._month && _day > d._day);
    }

private:
    int _year, _month, _day;
};

四、容器适配器深度解析

4.1 什么是容器适配器

适配器是一种设计模式,将已有类的接口转换为目标接口,stack/queue/priority_queue 都是 STL 容器适配器,不独立存储数据,只封装底层容器。

4.2 STL 默认底层容器

  • stack:默认 deque
  • queue:默认 deque
  • priority_queue:默认 vector + 堆算法

4.3 deque(双端队列)简介

deque 是分段连续 的双开口结构,支持 O(1) 头尾插删,扩容无需大量搬移数据,但不适合频繁遍历

4.4 为什么 stack/queue 默认用 deque

  1. stack/queue 不需要遍历,避开 deque 遍历效率低的缺陷;
  2. deque 头尾操作效率高,扩容成本远低于 vector,内存利用率优于 list;
  3. 完美适配 stack(尾插尾删)、queue(尾插头删)的操作需求。

4.5 通用版模拟实现(支持自定义底层容器)

栈通用实现
cpp 复制代码
#include <deque>
namespace bite {
template<class T, class Con = deque<T>>
class stack {
public:
    stack() {}
    void push(const T& x) { _c.push_back(x); }
    void pop() { _c.pop_back(); }
    T& top() { return _c.back(); }
    const T& top() const { return _c.back(); }
    size_t size() const { return _c.size(); }
    bool empty() const { return _c.empty(); }

private:
    Con _c;
};
}
队列通用实现
cpp 复制代码
#include <deque>
namespace man {
template<class T, class Con = deque<T>>
class queue {
public:
    queue() {}
    void push(const T& x) { _c.push_back(x); }
    void pop() { _c.pop_front(); }
    T& back() { return _c.back(); }
    const T& back() const { return _c.back(); }
    T& front() { return _c.front(); }
    const T& front() const { return _c.front(); }
    size_t size() const { return _c.size(); }
    bool empty() const { return _c.empty(); }

private:
    Con _c;
};
}

五、总结

  1. stack:后进先出,仅操作栈顶,底层封装 vector/deque;
  2. queue:先进先出,队尾入队、队头出队,底层封装 list/deque;
  3. priority_queue:堆结构,默认大顶堆,底层默认 vector;
  4. 三者均为容器适配器,STL 默认用 deque 作为 stack/queue 底层,兼顾效率与内存。
相关推荐
傻啦嘿哟32 分钟前
如何在 Python 中使用 colorama 库来给输出添加颜色
开发语言·python
CN-Dust34 分钟前
【C++】输入cin例题专题
java·c++·算法
geovindu2 小时前
go: Visitor Pattern
开发语言·设计模式·golang·访问者模式
宣宣猪的小花园.2 小时前
C语言重难点全解析:内存管理到位运算
c语言·开发语言·单片机
方安乐6 小时前
python之向量、向量和、向量点积
开发语言·python·numpy
小小小米粒7 小时前
Collection单列集合、Map(Key - Value)双列集合,多继承实现。
java·开发语言·windows
智者知已应修善业8 小时前
【51单片机中的打飞机设计】2023-8-25
c++·经验分享·笔记·算法·51单片机
czhc11400756638 小时前
C# 428 线程、异步
开发语言·c#
:1218 小时前
java基础
java·开发语言
SilentSamsara9 小时前
Python 环境搭建完整指南:从下载安装到运行第一个程序
开发语言·python