【转】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
それでも私の大好きな人
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步