• .size和.empty


    坑爹的list容器size方法--为了splice居然把复杂度设计为O(N)?

    能用empty的时候,不要用size

    empty可以保证常量复杂度,但list的size不保证

    链表长度必须要遍历全部的链表元素才能获得,而不是用一个变量来表示

    list size调用distance,distance内部遍历链表

    sgi设计list的思路何以如此与众不同呢(话说微软的STL实现就没有这个SIZE方法的效率问题)?

    看看作者自己的解释:http://home.roadrunner.com/~hinnant/On_list_size.html

    开篇点题,原来作者是为

    splice(iterator position, list& x, iterator first, iterator last);
    方法所取的折衷,为了它的实现而把size方法设计成了O(N)。
    splice方法就是为了把链表A中的一些元素直接串联到链表B中,如果size()设计为O(1)复杂度,那么做splice时就需要遍历first和last间的长度(然后把链表A保存的链表长度减去first和last(待移动的元素)之间的长度)!于是作者考虑到size方法设计为O(N),就无需在splice方法执行时做遍历了!
    看看splice的实现:

      void splice(iterator __position, list&, iterator __first, iterator __last) {
        if (__first != __last) 
          this->transfer(__position, __first, __last);
      }
    再看看transfer干了些什么:
      void transfer(iterator __position, iterator __first, iterator __last) {
        if (__position != __last) {
          // Remove [first, last) from its old position.
          __last._M_node->_M_prev->_M_next     = __position._M_node;
          __first._M_node->_M_prev->_M_next    = __last._M_node;
          __position._M_node->_M_prev->_M_next = __first._M_node; 
    
          // Splice [first, last) into its new position.
          _List_node_base* __tmp      = __position._M_node->_M_prev;
          __position._M_node->_M_prev = __last._M_node->_M_prev;
          __last._M_node->_M_prev     = __first._M_node->_M_prev; 
          __first._M_node->_M_prev    = __tmp;
        }
      }
    作者确实是考虑splice执行时,不用再做遍历,而是仅仅移动几个指针就可以了,因此牺牲了size的效率!


  • 相关阅读:
    HDU 2081 手机短号
    HDU 2053 Switch Game
    HDU 2040 亲和数
    HDU 2070 Fibbonacci Number
    redis集群安装2
    redis集群1
    批量更新sql
    centos 6升级 GCC 到4.8
    排序4 -- 插入排序
    排序3--选择排序
  • 原文地址:https://www.cnblogs.com/raichen/p/5808142.html
Copyright © 2020-2023  润新知