【问题标题】:Circular array (Queue) Iterator循环数组(队列)迭代器
【发布时间】:2019-03-10 03:18:14
【问题描述】:

我有一个用于队列的迭代器类(实现为循环数组)。我附上下面的代码。问题在于 ++ 运算符。一旦它到达数组的末尾,它就会回到它的开头,因此迭代器指向第一个元素。它工作正常,但我无法使用这种方法实现 then end() 迭代器。在队列类中返回 begin() 和 end() 迭代器的函数可以在底部看到。 end() 迭代器应该指向队列的尾部,但是当数组已满且尾部等于数组的大小时不起作用,++ 运算符将循环返回而不是让它返回真正的结束(),也就是后面指向的元素。关于这个问题有什么建议吗?

class IteratorForwQueue : std::iterator<std::forward_iterator_tag, P*> {
    public:
        typedef IteratorForwQueue iter;
        IteratorForwQueue(P* e, Queue* q) : elem(e), _queue(q) {}
        IteratorForwQueue(const IteratorForwQueue& it, Queue* q) :
            elem(it.elem), _queue(q) {}

        iter& operator++() {
            if(elem >= (_queue->_elems + (_queue->_size - 1)) &&
                            _queue->_rear != _queue->_size)
                elem = &(_queue->_elems[0]); // circle back passed the array
            else
                ++elem;
            return *this;
        }

        P& operator*() { return *elem;}
        P* operator->() { return elem; }
        bool operator==(const iter& it) { return elem == it.elem; }
        bool operator==(const P& e) { return e == *elem; }
        bool operator!=(const iter& it) { return elem != it.elem; }
        bool operator!=(const P& e) { return e != *elem; }
    private:
        P* elem;
        Queue<P>* _queue;
    }; // end of iterator class
// ....
IteratorForwQueue begin() { return IteratorForwQueue(_elems + _front, this); }
IteratorForwQueue end() { return IteratorForwQueue(_elems + _rear, this); }

【问题讨论】:

  • 你能负担得起浪费一个插槽并将其用作哨兵吗?
  • 队列的前面和后面会随着您入队和出队而变化。如果它发生变化,我不能有一个哨兵
  • 那么事情就是这样,如果你有一个队列实现为一个循环数组,你将如何实现它的迭代器的operator++?

标签: c++ arrays iterator queue


【解决方案1】:

这个怎么样,基于 end 不必是“过去的”迭代器的想法,它可以是任何东西:

class IteratorForwQueue : std::iterator<std::forward_iterator_tag, P*> {
public:
    typedef IteratorForwQueue iter;
    IteratorForwQueue(P* e, size_t sz, size_t rear) : elem(e), _base(e), _sz(sz), _rear(rear) {}
    IteratorForwQueue(const IteratorForwQueue& it, size_t sz) :
        elem(it.elem), _base(it.elem), _sz(sz) {}

    iter& operator++() {
       if(elem - _base == _rear) {
          elem = nullptr;
          _base = 0;
          _sz = 0;
          _rear = 0;
          return *this;
       } 
       if(elem >= _base + (_sz - 1))
            elem = _base; // circle back passed the array
        else
            ++elem;


        return *this;
    }

    P& operator*() { return *elem;}
    P* operator->() { return elem; }
    bool operator==(const iter& it) { return elem == it.elem; }
    bool operator==(const P& e) { return e == *elem; }
    bool operator!=(const iter& it) { return elem != it.elem; }
    bool operator!=(const P& e) { return e != *elem; }
private:
    P* elem;
    P* _base;  // can't access members of outer class
    size_t _sz; // can't access members of outer class
    size_t _rear;
}; // end of iterator class
// ....
IteratorForwQueue begin() { return IteratorForwQueue(_elems + _front, _size, _rear); }
IteratorForwQueue end() { return IteratorForwQueue(nullptr, 0, 0); }
const IteratorForwQueue cbegin() const { return     IteratorForwQueue(_elems + _front, _size); }
const IteratorForwQueue cend() const { return IteratorForwQueue(_elems + _rear, _size); }

顺便说一句,最好有一个指向原始数据结构的指针,使迭代器成为朋友类并按需获取_base_sz_rear

【讨论】:

  • 代码并没有简化,但我在考虑传递 this 指针而不是指向原始数据结构。那并修改 ++ 运算符的条件就可以了,仅当后部不等于大小时才返回(参见代码)。出于文档目的,如果您不介意,请将新代码复制到您的答案中以将其标记为答案,谢谢
猜你喜欢
  • 2023-03-07
  • 2016-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-24
相关资源
最近更新 更多