【问题标题】:Does a standard implementation of a Circular List exist for C++?C++ 是否存在循环列表的标准实现?
【发布时间】:2010-10-31 03:43:22
【问题描述】:

我想使用循环列表。

没有实现我自己的 (like this person did) 我有哪些选择?

具体来说,我想做的是遍历对象列表。当我的迭代器到达列表的末尾时,它应该自动返回到开头。 (是的,我意识到这可能很危险。)

See Vladimir's definition of a circular_iterator: "circular_iterator 永远不会与 CircularList::end() 相等,因此您始终可以取消引用此迭代器。"

【问题讨论】:

    标签: c++ data-structures circular-list


    【解决方案1】:

    没有标准的循环列表。

    不过,Boost 中有一个circular buffer,这可能会有所帮助。

    如果您不需要任何花哨的东西,您可以考虑只使用vector 并使用索引访问元素。您只需 mod 您的索引与向量的大小即可实现与循环列表大致相同的功能。

    【讨论】:

    • 谢谢纳夫!用向量的大小来修改索引就是这么简单的解决方案,不好意思没想到。
    • 如果您确保 vector 的大小是 2 的幂,那么不要使用模运算的昂贵开销,而是使用按位 & 运算符,因为它只需要一个周期.它的工作原理是这样的:(n mod (2^k)) == (n & (2^k - 1)) 例如n % 256 == (n & (255))
    • 编译器会在适合您的情况下将 mod 替换为位操作,除非您确实需要未优化的调试性能,否则无需混淆代码
    【解决方案2】:

    如果你想要一个看起来像迭代器的东西,你可以自己滚动,看起来像

    template <class baseIter>
    class circularIterator {
        private:
            baseIter cur;
            baseIter begin;
            baseIter end;
        public:
            circularIterator(baseIter b, baseIter e, baseIter c=b)
                :cur(i), begin(b), end(e) {}
            baseIter & operator ++(void) {++cur; if(cur == end) {cur = begin;}}
    };
    

    (其他迭代器操作留给读者练习)。

    【讨论】:

      【解决方案3】:
      list<int>::iterator circularNext(list<int> &l, list<int>::iterator &it)
      {
          return std::next(it) == l.end() ? l.begin() : std::next(it);
      }
      

      【讨论】:

        【解决方案4】:

        除了@captain-segfault 和@mahmoud-khaled 以迭代器为中心的答案之外,您还可以通过更改从中检索元素的操作将std::list 用作循环列表。在处理列表时,使用splice 将列表的一端移动到另一端。

        template <typename T>
        T & circularFront(std::list<T> & l)
        {
          l.splice(l.end(), l, l.begin());
          return l.back();
        }
        template <typename T>
        T & circularBack(std::list<T> & l)
        {
          l.splice(l.begin(), l, l.rbegin());
          return l.front();
        }
        

        【讨论】:

          【解决方案5】:

          我找到了这个解决方案。适合我。

          std::list<int> List{ 1,2,3,4,5,6 };
          
              auto it = List.end();
          
              it--;
          
              it._Ptr->_Next = List.begin()._Ptr; // Next Node of the last elemen is now first elemen of the List
              List.begin()._Ptr->_Prev = it._Ptr; // Prev Node of the first element is now Last node
          
              for (int num : List)
              {
                  std::cout << num << '\n';
              }
          

          在这种情况下,我们将无限循环。也应该向后工作。

          输出

          1
          2
          3
          4
          5
          6
          1
          2
          3
          4
          5
          6
          1
          .
          .
          

          【讨论】:

          • 嗨医生 smail,这里的问题不是关于使链表循环,Runcible 正在寻找一个循环的 list 类
          猜你喜欢
          • 1970-01-01
          • 2014-10-04
          • 1970-01-01
          • 2020-01-07
          • 1970-01-01
          • 1970-01-01
          • 2012-03-31
          • 2011-05-10
          • 2010-09-17
          相关资源
          最近更新 更多