我可以在环中实现迭代器end()吗?

时间:2016-11-25 11:38:19

标签: c++ data-structures iterator

首先,我无法在互联网上找到关于铃声数据结构的更多信息,所以这里是一个简短的实现,显示一个响铃是什么(根据我的讲师)

template<typename Key, typename Info>
class Ring
{
struct Node   // structure for storing the data
{
    Key k;
    Info inf;

    Node* next;
    Node* prev;
};

Node* any;  // pointer to a node belonging to the ring, NULL if the ring is empty
};

它类似于循环列表,但any可以指向结构中的任何元素,我们不关心顺序,我们添加的位置等。

除了我已经完成的项目的主要任务之外,我们必须以这样的方式实现迭代器,

for(auto it = r1.begin(); it != r1.end(); ++it)      // r1 is a ring
{ cout << *it << ' '; }

正常工作,即。打印整个戒指。

甚至可能吗?迭代器end()应指向一个地方,下一个元素将被添加,我们没有这样的观点。如果它被设置为any(与begin()相同),则根本不会执行循环,如果它被设置为any->prev,它将省略最后一个元素。

您有什么想法,我该如何实现?或者我是对的,这是不可能的?

2 个答案:

答案 0 :(得分:0)

end()在一个响铃的背景下毫无意义:你无法在一个响铃中识别出一个位置超过最后一个元素&#34;,这是什么if是。

迭代一个环的惯用方法是从任意点向相反方向发送两个迭代器,并在两个迭代器到达后终止,其中一个具有#34;处理&#34;,相同的元素。 / p>

答案 1 :(得分:0)

对于单项铃声,如果begin()end()都必须引用节点,则begin()end()会明确引用相同的节点,但它们可以&# 39; t比较相等,因为这会导致循环在第一次迭代之前退出。

因此,您可以得出结论,对于这些迭代器,不能仅根据它们所引用的节点来定义相等性。

即。你只需要以合适的方式定义迭代器相等性。

在许多情况下,结束迭代器只是一个默认构造的迭代器。

所以这不是什么新鲜事。

示例:

#include <assert.h>         // assert.h
#include <iterator>         // std::(iterator, forward_iterator_tag)
#include <utility>          // std::(pair)

namespace cppx {
    class Non_copyable
    {
    private:
        Non_copyable( Non_copyable const& ) = delete;
        auto operator=( Non_copyable const& ) -> Non_copyable& = delete;
    public:
        auto operator=( Non_copyable&& ) {}
        Non_copyable() {}
        Non_copyable( Non_copyable&& ) {}
    };
}  // namespace cppx

namespace my {
    using std::pair;
    using std::iterator;
    using std::forward_iterator_tag;

    template< class Key, class Value >
    class Ring
        : public cppx::Non_copyable
    {
    public:
        using Pair = pair<Key, Value>;      // Movable

    private:
        struct Node             // For storing the data
        {
            // Key key;
            // Value value;
            Pair    kv;

            Node*   next;
            Node*   prev;
        };

        class Iterator
            : public iterator<forward_iterator_tag, Pair>
        {
        private:
            Node*   p_first_;
            Node*   p_current_;

            auto is_end() const -> bool { return p_first_ == nullptr; }

            void advance()
            {
                p_current_ = p_current_->next;
                if( p_current_ == p_first_ )
                {
                    p_first_ = nullptr;
                    assert( is_end() );
                }
            }

        public:
            friend
            auto operator==( Iterator const& a, Iterator const& b )
                -> bool
            { return !!a.p_first_ == !!b.p_first_ and a.p_current_ == b.p_current_; }

            friend
            auto operator!=( Iterator const& a, Iterator const& b )
                -> bool
            { return not( a == b ); }

            auto operator++()
                -> Iterator&
            {
                advance();
                return *this;
            }

            auto operator++( int )
                -> Iterator
            {
                Iterator result = *this; 
                advance();
                return result;
            }

            auto operator*() const
                -> Pair const&
            { return p_current_->kv; }

            auto operator->() const
                -> Pair const*
            { return &p_current_->kv; }

            Iterator( Node* p, bool be_end = false )
                : p_first_( be_end? nullptr : p )
                , p_current_( p )
            {}
        };

        Node*   p_current_;     // Node in the ring, 0 if the ring is empty.

    public:
        // TODO: add new node, before current node if any.
        void add( Pair kv );

        // TODO: advance n positions, backward for negative n.
        void advance( int const n = 1 );

        // TODO: a unique id for current position.
        auto current_position() const -> void const*;

        auto is_empty() const -> bool;

        auto current() const -> Pair const&;

        auto begin() const -> Iterator      { return {p_current_}; }
        auto end() const -> Iterator        { return {p_current_, true}; }

        Ring(): p_current_() {}

        Ring( Ring&& other )
            : p_current_( other.p_current_ )
        { other.p_current_ = nullptr; }
    };
}  // namespace my

#include <iostream>
using namespace std;

auto operator<<( ostream& stream, my::Ring<int, int>::Pair const& kv )
    -> ostream&
{ return stream << "{" << kv.first << ", " << kv.second << "}"; }

auto main()
    -> int
{
    using Ring = my::Ring<int, int>;

    Ring r;
    for( int i : {3, 1, 4, 1, 5, 9, 2, 6, 5, 4} )
    {
        r.add( {i, i*i} );
    }

    // Output via explicit iteration.
    auto const first = r.current_position();
    do
    {
        if( r.current_position() != first ) { cout << ", "; }
        cout << r.current();
        r.advance();
    } while( r.current_position() != first );
    cout << "\n";

    // Output via range based `for` using `begin` and `end` iterators.
    int count = 0;
    for( Ring::Pair const& kv : r )
    {
        if( count++ > 0 ) { cout << ", "; }
        cout << kv;
    }
    cout << "\n";
}

输出:

{3, 9}, {1, 1}, {4, 16}, {1, 1}, {5, 25}, {9, 81}, {2, 4}, {6, 36}, {5, 25}, {4, 16}
{3, 9}, {1, 1}, {4, 16}, {1, 1}, {5, 25}, {9, 81}, {2, 4}, {6, 36}, {5, 25}, {4, 16}