让我们关注 const 迭代器。这样的迭代器应该为每个双端队列保存一个迭代器,但也应该为它们的每个端保存一个迭代器(为什么需要这个在下面解释)。但是这些迭代器应该保存在向量而不是双端队列中,因为您永远不会从这些容器的任何一端推送或弹出,因为此类迭代器的生命周期会随着数据结构的修改而结束。
所以基本上,你需要以下结构:
struct const_iterator {
vector<deque<int>::const_iterator> iterators;
vector<deque<int>::const_iterator> ends;
//...
};
现在,您需要实现递增运算符(也许您还需要一个递减运算符,可以类似地实现),以及取消引用运算符。
自增操作符需要找到当前指向最小元素的双端队列迭代器,并自增。
解引用操作符还需要找到当前指向最小元素的deque迭代器,并解引用那个。
如果您正在寻找当前最小的元素,请忽略已经指向其末尾的双端队列。为此,您需要所有双端队列的结束迭代器。记住另一个成员变量中当前最小的元素可能会有所帮助,这样取消引用就变成了一个常数时间的操作。我们将当前的迭代器作为迭代器存储到迭代器的向量中,这样我们就可以递增它(因此向量中的迭代器会改变)。
struct nested_deque_iterator {
vector<deque<int>::const_iterator> iterators;
vector<deque<int>::const_iterator> ends;
vector<deque<int>::const_iterator>::iterator current;
bool at_end = false;
};
更新最小元素可以在辅助函数中实现,它修改成员变量current 以及at_end。这需要在构造函数中调用才能正确初始化成员变量:
void update_current() {
if (!at_end && iterators.size() > 0) {
// At the beginning, we assume that we didn't find any
// new "next smaller element" in any deque.
at_end = true;
// Iterate through the deques (with two iterators in parallel)
for (auto i = iterators.begin(), e = ends.begin();
i != iterators.end() && e != ends.end();
++i, ++e)
{
// We ignore deques which are already at their end
if (i != e) {
// If we found a smaller next element (or the first try)...
if (at_end || *i < *next) {
// ... then replace the current iterator with it:
at_end = false;
current = i;
}
}
}
}
}
然后,解引用变得像解引用当前迭代器一样简单两次(因为它是迭代器向量的迭代器......我知道这有点令人困惑......)
int operator *() const {
return **current;
}
而自增将自增(取消引用的)当前迭代器,并调用辅助函数对其进行更新(这是预自增运算符):
nested_deque_iterator& operator++() {
if (!at_end) {
++(*current);
update_current();
}
}
你可以通过预自增的方式实现后自增运算符:
nested_deque_iterator operator++(int) {
nested_deque_iterator old(*this);
++(*this);
return old;
}
我们还需要相等运算符来比较迭代器:
bool operator==(const nested_deque_iterator &o) const {
// If either iterator is at the end, don't dereference current!
if (at_end || o.at_end) {
return at_end == o.at_end;
}
return *current == *(o.current);
}
最后是不等式运算符:
bool operator!=(const nested_deque_iterator &o) const {
return !(*this == o);
}
最后,为嵌套的双端队列编写一个开始和结束构造辅助函数。
nested_deque_iterator nested_deque_begin(const deque<deque<int>> & deques) {
vector<deque<int>::const_iterator> iterators;
vector<deque<int>::const_iterator> ends;
for (const auto & d : deques) {
iterators.push_back(d.begin());
ends.push_back(d.end());
}
return { iterators, ends };
}
nested_deque_iterator nested_deque_end(const deque<deque<int>> & deques) {
vector<deque<int>::const_iterator> ends;
for (const auto & d : deques) {
ends.push_back(d.end());
}
return { ends, ends };
}
如果你愿意,还有一个容器适配器(如果你还没有这样的),它使用这些构造辅助函数作为它们的默认开始和结束方法:
struct nested_deque {
deque<deque<int>> deques;
//...
}
nested_deque_iterator begin(const nested_deque & nd) {
return nested_deque_begin(nd.deques);
}
nested_deque_iterator end(const nested_deque & nd) {
return nested_deque_end(nd.deques);
}
所以你可以写:
deque<deque<int>> mydeque = ...;
for (int i : nested_deque{mydeque}) {
// Here you go.
}
完整的实现是可用的here。