• 【转】std::list中size()方法的时间复杂度


      标准STL容器List(Linux GNU,sgi的实现),其size()函数的要遍历所有list中的元素来获得链表长度,来看看它的实现:

    1 size_type size() const {
    2     size_type __result = 0;
    3     distance(begin(), end(), __result);
    4     return __result;
    5   }

      其通过调用distance()函数来计算元素个数,而distance方法的实现如下:

    1 template <class _InputIterator, class _Distance>
    2 inline void distance(_InputIterator __first, 
    3                      _InputIterator __last, _Distance& __n)
    4 {
    5   __STL_REQUIRES(_InputIterator, _InputIterator);
    6   __distance(__first, __last, __n, iterator_category(__first));
    7 }

      又封了一层_distance(),看看它做了什么:

     1 template <class _InputIterator>
     2 inline typename iterator_traits<_InputIterator>::difference_type
     3 __distance(_InputIterator __first, _InputIterator __last, input_iterator_tag)
     4 {
     5   typename iterator_traits<_InputIterator>::difference_type __n = 0;
     6   while (__first != __last) {
     7     ++__first; ++__n;
     8   }
     9   return __n;
    10 }

      原来是遍历!为什么获得链表长度必须要遍历全部的链表元素才能获得,而不是用一个变量来表示呢?sgi设计list的思路何以如此与众不同呢

      原来作者是为了

    splice(iterator position, list& x, iterator first, iterator last);

      方法所取的折衷。list 是链表结构,它的优势就在于可以 O(1) 的时间复杂度任意插入甚至拼接 list 片段。list::splice() 是一个很强大的功能,它可在任意位置拼接两个 list。如果我们在类内部以一个变量储存 list 的长度,那么splice()之后新list的长度就需要遍历待移动元素的first和last间的长度(然后把链表A保存的链表长度减去first和last之间的长度)。于是作者考虑将size()方法设计为O(N),就无需在splice()方法执行时做遍历了。

    1 void splice(iterator __position, list&, iterator __first, iterator __last) {
    2     if (__first != __last) 
    3       this->transfer(__position, __first, __last);
    4   }

      再看看transfer干了些什么:

     1 void transfer(iterator __position, iterator __first, iterator __last) {
     2     if (__position != __last) {
     3       // Remove [first, last) from its old position.
     4       __last._M_node->_M_prev->_M_next     = __position._M_node;
     5       __first._M_node->_M_prev->_M_next    = __last._M_node;
     6       __position._M_node->_M_prev->_M_next = __first._M_node; 
     7  
     8       // Splice [first, last) into its new position.
     9       _List_node_base* __tmp      = __position._M_node->_M_prev;
    10       __position._M_node->_M_prev = __last._M_node->_M_prev;
    11       __last._M_node->_M_prev     = __first._M_node->_M_prev; 
    12       __first._M_node->_M_prev    = __tmp;
    13     }
    14   }

      作者确实是考虑splice执行时,不用遍历,而是仅仅移动几个指针就可以了,因此牺牲了size的效率!

      转自:https://blog.csdn.net/russell_tao/article/details/8572000

  • 相关阅读:
    使用python实现深度神经网络 1(转)
    OHDSI——数据标准化
    TensorFlow相关
    语言模型和共现矩阵(转)
    cd4与cd8比值的意义
    python之使用set对列表去重,并保持列表原来顺序(转)
    Python 汉字转拼音
    Hadoop的启动和停止说明
    Scikit-learn 概述
    病历智能分析系统的研究与实现(转)
  • 原文地址:https://www.cnblogs.com/codingmengmeng/p/13604620.html
Copyright © 2020-2023  润新知