在C++ STL中,queue和deque的入队和出队操作有明确的规范,但它们的行为有所不同。以下是详细说明:
1. std::queue(队列,FIFO)
- 入队(push):加到队尾
queue<int> q; q.push(1); // 队尾:[1] q.push(2); // 队尾:[1,2] - 出队(pop):从队首移除
q.pop(); // 移除1,剩下:[2] - 访问:
q.front():队首元素q.back():队尾元素
2. std::deque(双端队列)
支持两端操作:
- 队尾操作:
deque<int> dq; dq.push_back(1); // 队尾:[1] dq.push_back(2); // 队尾:[1,2] dq.pop_back(); // 移除2,剩下:[1] - 队首操作:
dq.push_front(0); // 队首:[0,1] dq.pop_front(); // 移除0,剩下:[1] - 随机访问:
dq[0]; // 访问第0个元素
关键区别
| 操作 | queue |
deque |
|---|---|---|
| 入队 | 仅push(队尾) |
push_back/push_front |
| 出队 | 仅pop(队首) |
pop_back/pop_front |
| 访问队首 | front() |
front() |
| 访问队尾 | back() |
back() |
| 随机访问 | 不支持 | 支持(如dq[2]) |
为什么滑动窗口用deque?
在滑动窗口最小值的算法中,我们需要:
- 从队尾移除比当前元素大的值(保持单调性)
- 从队首移除过期元素(超出窗口范围)
- 从队尾添加新元素
这正是deque支持的高效操作:
deque<int> dq;
// 维护单调递增队列
for (int i = 0; i < n; ++i) {
// 1. 移除队尾比当前元素大的
while (!dq.empty() && nums[dq.back()] >= nums[i]) {
dq.pop_back();
}
// 2. 添加当前索引
dq.push_back(i);
// 3. 移除过期队首
while (dq.front() <= i - k) {
dq.pop_front();
}
// 当前窗口最小值是nums[dq.front()]
}
总结
-
queue:严格的FIFO,只能操作队首和队尾 -
deque:灵活的双端操作,适合需要两端修改的场景(如滑动窗口)include
include
include
using namespace std;
int main() {
vectorcars;
vectorrequires;
int num;// 读取cars数组
while (cin >> num) {
cars.push_back(num);
if (cin.get() == '\n') break;
}// 读取requires数组
while (cin >> num) {
requires.push_back(num);
if (cin.get() == '\n') break;
}deque
q(requires.begin(), requires.end());
int K = 0;
int allocations = 0;
int remaining = q.size();for (int car : cars) {
K += car;while (!q.empty()) {
int max_len = 0;
int current_sum = 0;
int left = 0;
int best_left = -1;
int best_right = -1;// 滑动窗口找最长子序列
for (int right = 0; right < q.size(); ++right) {
current_sum += q[right];
while (current_sum > K && left <= right) {
current_sum -= q[left];
left++;
}
if (right - left + 1 > max_len) {
max_len = right - left + 1;
best_left = left;
best_right = right;
}
}if (max_len == 0) {
break; // 无法分配,退出循环
}// 执行分配
allocations++;
remaining -= max_len;// 移除已分配的元素
dequenew_q;
for (int i = 0; i < q.size(); ++i) {
if (i < best_left || i > best_right) {
new_q.push_back(q[i]);
}
}
q = new_q;// 重置K,因为已分配
K = 0;
if (q.empty()) break; // 需求队列为空,无需继续
}
}cout << allocations << " " << remaining << endl;
return 0;
}
浙公网安备 33010602011771号