在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<int> 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; // 移除已分配的元素 deque<int> new_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号