list 内部提供一个所谓的迁移动作(transfer):将某连续范围的元素迁移到某个特定位置之前。技术上很简单,节点间的指标移动而已。这个动作为其它的复杂动作如 splice, sort, merge 等奠定良好的基础。下面是 transfer 的源码:
// 将 [first,last) 内的所有元素搬移到 position 之前 void transfer(iterator position, iterator first, iterator last) { if (position != last) // 如果last == position, 则相当于链表不变化, 不进行操作 { (*(link_type((*last.node).prev))).next = position.node; //(1) (*(link_type((*first.node).prev))).next = last.node; //(2) (*(link_type((*position.node).prev))).next = first.node; //(3) link_type tmp = link_type((*position.node).prev); //(4) (*position.node).prev = (*last.node).prev; //(5) (*last.node).prev = (*first.node).prev; //(6) (*first.node).prev = tmp; //(7) } }以上七步操作图解: 通过transfer():splice(),merge(),reverse(),sort()都能很方便的完成。
list::splice 许多版本:
// 将 x 接合于 position 所指位置之前。x 必须不同于 *this。 void splice(iterator position, list& x) { if (!x.empty()) transfer(position, x.begin(), x.end()); } //将 i 所指元素接合于 position 所指位置之前。position 和 i 可指向同一个 list。 void splice(iterator position, list&, iterator i) { iterator j = i; ++j; if (position == i || position == j) return; transfer(position, i, j); } // 将 [first,last) 内的所有元素接合于 position 所指位置之前。 // position 和[first,last)可指向同一个 list, // 但 position 不能位于[first,last)之内。 void splice(iterator position, list&, iterator first, iterator last) { if (first != last) transfer(position, first, last); }merge函数
// merge() 将 x 合并到 *this 身上。两个 lists 的内容都必须先经过递增排序。 template <class T, class Alloc> void list<T, Alloc>::merge(list<T, Alloc>& x) { iterator first1 = begin(); iterator last1 = end(); iterator first2 = x.begin(); iterator last2 = x.end(); // 注意:前提是,两个lists都已经递增排序 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); }reverse函数
// reverse() 将 *this 的内容逆向重置 template<class T, class Alloc> void list<T,Alloc>::reverse() { // 以下判断,如果是空白串行,或仅有㆒个元素,就不做任何动作。 // 使用 size() == 0 || size() == 1 来判断,虽然也可以,但是比较慢。 if (node->next == node || link_type(node->next->next == node)) { return; } iterator first = begin(); ++first; while (first != end()) { iterator old = first; ++first; transfer(begin(),old,first); } }sort函数
// list 不能使用 STL 算法 sort(),必须使用自己的 sort() member function, // 因为 STL 算法 sort() 只接受 RamdonAccessIterator. // 本函式采用 quick sort template <class T, class Alloc> void list<T, Alloc> :: sort(){ // 判断链表是否为空或者只有一个元素,就不做任何动作。 // 使用 size() == 0 || size() == 1 来判断,虽然也可以,但是比较慢。 if(node->next == node || link_type(node->next)->next == node){ return; } list<T, Alloc> carry; list<T, 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]); }