STL Learning _list Chapter

Source: Internet
Author: User

STL Learning--list Chapter
  • Brief introduction

    Unlike vectors, the list does not use contiguous space, but instead inserts or deletes an element each time it configures or frees an element space. So the list of the use of space is accurate, do not waste any space. The list inserts or deletes elements from any position, and the constant time is complete.
    The use of lists and vectors depends on the number of elements, the structural complexity of the elements, and the nature of the access behavior of the elements.

  • List node

    The list itself is different from the list node, and list is a doubly linked list. The node information is as follows:

    struct _List_node_base {  _List_node_base* _M_next;    // 前向指针  _List_node_base* _M_prev;    // 后向指针};// List节点template <class _Tp>struct _List_node : public _List_node_base {  _Tp _M_data;};
  • Iterator to List

    Because the list does not use contiguous storage space, you cannot use a normal pointer as an iterator like a vector. The list iterator must have the ability to point to the list node and to perform the correct increment, decrement, value, member access, and so on. The list in the STL is a two-way listing, so the iterator needs to have a forward, post-shift capability, so use bidirectional Iterator. The important nature of list: insert operation, the join operation will not cause the original list iterator to fail . In a list** delete operation, only the iterator that points to the deleted element is invalidated * *, and no other iterators are affected.

    Template<class _TP, Class _ref, class _ptr>struct _list_iterator:public _list_iterator_base {typedef _List_itera  Tor<_tp,_tp&,_tp*> iterator;  typedef _list_iterator<_tp,const _TP&AMP;,CONST _tp*> const_iterator;  typedef _list_iterator<_tp,_ref,_ptr> _SELF;  typedef _TP VALUE_TYPE;  typedef _ptr Pointer;  typedef _REF Reference;     typedef _list_node<_tp> _node; Inside the iterator, of course, there is a normal pointer to the List node//constructor _list_iterator (_node* __x): _list_iterator_base (__x) {} _list_iterator () {} _lis T_iterator (const iterator& __x): _list_iterator_base (__x._m_node) {}//following the iterator value (dereference), get the data value of the node reference operator* () const {return ((_node*) _m_node)->_m_data;} #ifndef __sgi_stl_no_arrow_operator//The following is the standard practice for member access (member access) operators of iterators Pointer operator-> () const {return & (O Perator* ());    } #endif/* __sgi_stl_no_arrow_operator///to the iterator to accumulate 1, is to advance a node _self& operator++ () {this->_m_incr ();  return *this; }  _self operator++ (int) {_self __tmp = *this;    THIS-&GT;_M_INCR ();  return __tmp;    }//To the iterator minus 1, is to back a node _self& operator--() {THIS-&GT;_M_DECR ();  return *this;    } _self operator--(int) {_self __tmp = *this;    THIS-&GT;_M_DECR ();  return __tmp; }};
  • List data structure

    List is not only a doubly linked list, but also a circular doubly linked list. Therefore, only one pointer is needed to fully represent the entire list. For a front-closed post-open interval, you need to have the pointer node perform a blank node that is deliberately placed on the tail end to become the last iterator.

    Insert a node as the head node void Push_front (const _tp& __x) {insert (Begin (), __x);}  void Push_front () {Insert (begin ());}  Insert a node as the tail node void push_back (const _tp& __x) {Insert (end (), __x);} void Push_back () {Insert (end ());}  Remove head node void Pop_front () {Erase (Begin ());}    Remove tail node void Pop_back () {Iterator __tmp = end ();  Erase (--__TMP);  }//forward operation iterator begin () {return (_node*) (_m_node->_m_next);}  Const_iterator begin () const {return (_node*) (_m_node->_m_next);}  The back Operation iterator end () {return _m_node;}  Const_iterator End () const {return _m_node;}  Reverse_iterator Rbegin () {return reverse_iterator (end ());}  Const_reverse_iterator Rbegin () const {return const_reverse_iterator (end ());}  Reverse_iterator rend () {return reverse_iterator (begin ());}  Const_reverse_iterator rend () const {return const_reverse_iterator (begin ());}  Produces an empty list bool empty () const {return _m_node->_m_next = = _m_node;} Size_type siZe () const {Size_type __result = 0;    Distance (begin (), End (), __result);  return __result;  } size_type max_size () const {return Size_type (-1);}  The contents of the header node (element value) reference front () {return *begin ();}  Const_reference () const {return *begin ();}  The contents of the tail node (element value) reference back () {return * (--end ());} Const_reference back () const {return * (--end ());}
  • List Construction and memory management

    The list uses alloc as the Space Configurator and uses List_node_allocator to facilitate node-size configuration units. where List_node_allocator (n) represents the configuration of N-node space. One of the Get_node (), Put_node (), Create_node (), Destory_node () respectively represents the configuration, release, construction, and destruction of a node.

      Template <class _tp, class _alloc>class _list_base {public:typedef _alloc allocator_type;  Configures a node and returns Allocator_type Get_allocator () const {return allocator_type ();}    _list_base (const allocator_type&) {_m_node = _m_get_node ();    _m_node->_m_next = _m_node;  _m_node->_m_prev = _m_node;    } ~_list_base () {clear ();  _m_put_node (_m_node); } void Clear ();p rotected://Dedicated Space Configurator, one node size per configuration typedef simple_alloc<_list_node<_tp>, _alloc> _alloc_type  ;  Configure a node and pass it back to _list_node<_tp>* _m_get_node () {return _alloc_type::allocate (1);}   Release a node void _m_put_node (_list_node<_tp>* __p) {_alloc_type::d eallocate (__p, 1);}    Generates (configures and constructs) a node with element values _node* _m_create_node (const _tp& __x) {_node* __p = _m_get_node ();    __stl_try {_construct (&__p->_m_data, __x);    global function, construct/destructor Basic tool} __stl_unwind (_m_put_node (__p));  return __p; }protected: _list_node<_tp>* _m_node;};  
  • List element operation

    List operations mainly include Push_front (), push_back (), Erase (), Pop_front (), Pop_back (), clear (), remove (), unique (), splice (), merge (), Reverse (), sort (), and so on. See below for source analysis.

    Clear all nodes (entire list) template <class _tp, Class _alloc>void _list_base<_tp,_alloc>::clear () {_list_node<_tp&  gt;* __cur = (_list_node<_tp>*) _m_node->_m_next;    while (__cur! = _m_node) {//Traverse each node _list_node<_tp>* __tmp = __cur;    __cur = (_list_node<_tp>*) __cur->_m_next;                   _destroy (&__tmp->_m_data);  Destroy (deconstruct and release) a node _m_put_node (__tmp);  }//Reply node original state _m_node->_m_next = _m_node; _m_node->_m_prev = _m_node;} Insert a node at the point where the iterator position, with the contents x iterator insert (iterator __position, const _tp& __x) {_node* __tmp = _m_create_nod            E (__x);    Generate a node (set content X)//adjust bidirectional pointer, insert tmp into __tmp->_m_next = __position._m_node;    __tmp->_m_prev = __position._m_node->_m_prev;    __position._m_node->_m_prev->_m_next = __tmp;    __position._m_node->_m_prev = __tmp;  return __tmp; } void Insert (iterator __pos, size_type __n, const _tp& __x) {_m_fill_insert (__pos, __n, __x);   } void _m_fill_insert (iterator __pos, size_type __n, const _tp& __x);  Insert a node as the head node void Push_front (const _tp& __x) {insert (Begin (), __x);}  void Push_front () {Insert (begin ());}  Insert a node as the tail node void push_back (const _tp& __x) {Insert (end (), __x);}  void Push_back () {Insert (end ());} Remove iterator position node iterator erase (iterator __position) {_list_node_base* __next_node = __position._m_node->_m_ne    xt    _list_node_base* __prev_node = __position._m_node->_m_prev;    _node* __n = (_node*) __position._m_node;    __prev_node->_m_next = __next_node;    __next_node->_m_prev = __prev_node;    _destroy (&__n->_m_data);    _m_put_node (__n);  Return iterator ((_node*) __next_node);  } Iterator Erase (iterator __first, iterator __last); Clears all nodes (entire list) void Clear () {_base::clear ();} Move all elements within [First,lat] to position before void transfer (iterator __position, iterator __first, iterator __last) {if (__posit Ion! = __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;       }}public: x must be different from *this void splice (iterator __position, list& __x) {if (!__x.empty ()) until X is connected to the position indicated by position  This->transfer (__position, __x.begin (), __x.end ()); }//The element I refers to is before the position indicated by position.    Position and I can point to the same list void splice (iterator __position, List&, iterator __i) {iterator __j = __i;    ++__j;    if (__position = = __i | | __position = = __j) return;  This->transfer (__position, __i, __j); }//Connect all elements in [first,last] to positionRefer to position before//position and [first,last] can point to the same list//But position cannot be located within [first,last] void splice (iterator __position, List&, ite  Rator __first, iterator __last) {if (__first! = __last) This->transfer (__position, __first, __last); }//removes all elements of the value value from the template <class _tp, class _alloc>void LIST&LT;_TP, _alloc>::remove (const _tp& __value)  {Iterator __first = begin ();  Iterator __last = end ();    while (__first! = __last) {//Traverse each node iterator __next = __first;    ++__next;       if (*__first = = __value) erase (__first);  Remove __first = __next when found; }}//removes contiguous elements of the same value. Note that only "continuous and identical elements" will be removed from the remaining template <class _tp, class _alloc>void list<_tp, _alloc>::unique () {iterator __  First = begin ();  Iterator __last = end ();                   if (__first = = __last) return;  Empty list, nothing to do iterator __next = __first; while (++__next! = __last) {//Traverse each node if (*__first = = *__next)//If there is a phase in this section The same element ERase (__next);                            Remove the Else __first = __next;                              Adjust pointer __next = __first; Fix section range}}//merge () merges X into *this. The contents of the two lists must first be sorted by incrementing the template <class _tp, class _alloc>void list<_tp, _alloc>::merge (LIST&LT;_TP, _alloc  >& __x) {iterator __first1 = begin ();  Iterator __last1 = end ();  Iterator __first2 = __x.begin ();  Iterator __last2 = __x.end ();      Note: The premise is that two lists are already incrementing the sort while (__first1! = __last1 && __first2! = __last2) if (*__first2 < *__first1) {      Iterator __next = __first2;      Transfer (__first1, __first2, ++__next);    __first2 = __next;  } else ++__first1; if (__first2! = __last2) Transfer (__last1, __first2, __last2);}  The List is reversed with the inline void __list_base_reverse (_list_node_base* __p) {_list_node_base* __tmp = __p;    do {__std::swap (__tmp->_m_next, __tmp->_m_prev);     __tmp = __tmp->_m_prev;  Old next node was now prev. } WHIle (__tmp! = __p);} Reverse () Reverse *this content reset Template <class _tp, class _alloc>inline void List<_tp, _alloc>::reverse () {__list    _base_reverse (This->_m_node);} List cannot use the STL algorithm sort () and must use its own sort () function//Because the STL algorithm sort () only accepts randomaccesssiterator//This function uses quick sort to implement template <  Class _TP, Class _alloc>void list<_tp, _alloc>::sort () {//Do nothing if the list has length 0 or 1. The following judgment, if it is an empty list, or only one element, does not do anything//use size () ==0| | Size () ==1 to judge, although it can, but slower if (_m_node->_m_next! = _m_node && _m_node->_m_next->_m_next! = _m_node) {/    /Some new lists, as intermediary data storage area LIST&LT;_TP, _alloc> __carry;    LIST&LT;_TP, _alloc> __counter[64];    int __fill = 0;      while (!empty ()) {__carry.splice (__carry.begin (), *this, Begin ());      int __i = 0;        while (__i < __fill &&!__counter[__i].empty ()) {__counter[__i].merge (__carry);      __carry.swap (__counter[__i++]);               } __carry.swap (__counter[__i]); if (__i = = __fill) ++__fill;    } for (int __i = 1; __i < __fill; ++__i) __counter[__i].merge (__counter[__i-1]);  Swap (__COUNTER[__FILL-1]); }}
  • Reference documents

    STL Source Code Analysis--Houtie

    STL Source Code

STL Learning _list Chapter

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.