容器适配器
什么是容器适配器?
定义
容器适配器不是“新容器”,而是对已有容器的接口封装,
用来限制功能、改变访问方式,从而形成特定的数据结构语义。
| 适配器 | 对应数据结构 |
|---|---|
stack | 栈(LIFO) |
queue | 队列(FIFO) |
priority_queue | 优先级队列(堆) |
适配器
复用已有实现,不暴露其全部接口,只提供“需要的那部分能力”。
👉 STL 的容器适配器:
内部用的是已有容器
对外只暴露特定接口
刻意隐藏 iterator / 随机访问能力
为什么要设计容器适配器?
例子:用 vector 模拟栈
👉 vector 的接口“太自由”,无法约束使用者
vector<int> v;
v.push_back(1);
v.push_back(2);
v.pop_back();
v.insert(v.begin(), 100); // ❌ 破坏“栈”的语义
v[0] = 999; // ❌ 非法访问
容器适配器做了三件事:
限制接口(只给 push / pop / top)
固定访问规则(LIFO / FIFO / 优先级)
防止误用(根本不给 iterator)
STL 三大容器适配器详解
(一)stack —— 栈(LIFO)
1️⃣ 定义与本质
template<
class T,
class Container = deque<T>
> class stack;
默认底层容器:
deque也可以用:
vector、list
2️⃣ 对外接口(非常少)
| 接口 | 说明 |
|---|---|
push(x) | 入栈 |
pop() | 出栈 |
top() | 访问栈顶 |
empty() | 是否为空 |
size() | 元素个数 |
3️⃣ 底层实现思想(本质)
template<class T, class Container>
class stack {
protected:
Container c; // 真正存数据的容器
public:
void push(const T& x) { c.push_back(x); }
void pop() { c.pop_back(); }
T& top() { return c.back(); }
};
(二)queue—— 队列(FIFO)
1️⃣ 定义与本质
template<
class T,
class Container = deque<T>
> class queue;
默认:
deque不能用
vector(没有pop_front)
2️⃣ 对外接口
| 接口 | 说明 |
|---|---|
push(x) | 入队(尾) |
pop() | 出队(头) |
front() | 队头 |
back() | 队尾 |
empty() | 判空 |
size() | 大小 |
3️⃣ 底层逻辑
void push(const T& x) { c.push_back(x); }
void pop() { c.pop_front(); }
(三)deque
1️⃣ 定义
deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组。
2️⃣ 缺陷
与vector比较,deque的优势是:
头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是必vector高的。
与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段。
但是,deque有一个致命缺陷:
不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构 时,大多数情况下优先考虑vector和list,deque的应用并不多 。
3️⃣ 为什么选择deque作为stack和queue的底层默认容器
1. stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作。
2. 在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);
queue中的元素增长时,deque不仅效率高,而且内存使用率高。
(四)priority_queue —— 优先级队列(堆)
1️⃣ 定义(最重要)
template<
class T,
class Container = vector<T>,
class Compare = less<T>
> class priority_queue;
默认是:
vector + 大根堆
top()是 最大值
2️⃣ 对外接口
| 接口 | 说明 |
|---|---|
push(x) | 插入元素 |
pop() | 删除优先级最高元素 |
top() | 访问最高优先级 |
empty() | 判空 |
size() | 个数 |
3️⃣ 底层实现思想(核心) 本质是堆(heap)
push -> push_back -> adjust_up
pop -> swap + pop_back -> adjust_down
容器适配器 vs 底层容器
| 维度 | 容器 | 容器适配器 |
|---|---|---|
| 是否存数据 | ✅ | ❌(只是封装) |
| 是否有 iterator | ✅ | ❌ |
| 接口是否自由 | 高 | 极低 |
| 是否强调语义 | 弱 | 强 |
| 是否可随机访问 | 视容器 | ❌ |
更多推荐
所有评论(0)