list源碼4(參考STL源碼--侯捷):transfer、splice、merge、reverse、sort
list源碼1(參考STL源碼--侯捷):list節點、叠代器、數據結構
list源碼2(參考STL源碼--侯捷):constructor、push_back、insert
list源碼3(參考STL源碼--侯捷):push_front、push_back、erase、pop_front、pop_back、clear、remove、unique
list源碼4(參考STL源碼--侯捷):transfer、splice、merge、reverse、sort
transfer
list內部提供一個所謂的遷移技術:transfer,將某連續範圍的元素遷移到某個指定的位置之前:
//將[first,last]內所有元素移動到position之前
void transfer(iterator position,iterator first,iterator last){ if(position!=last){ (*(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 temp=link_type((*position.node).prev); //4 (*position.node).prev=(*last.node).prev; //5 (*last.node).prev=(*first.node).prev; //6 (*first.node).prev=temp; //7 } }transfer所接受的[first,last]區間,可以存在同一個list裏面,上述transfer並非公開接口,list的公開接口是splice;splice:將某個連續範圍的元素從一個list移到另一個list的某個定點,使用如下:
#include<bits/stdc++.h> using
View Codenamespace std; int main() { list<int> l1={0,1,2,3,4,5}; int a[4]={11,12,13,14}; list<int> l2={a,a+4}; list<int>::iterator it=find(l1.begin(),l1.end(),3); list<int>::iterator first=l2.begin(); list<int>::iterator last=l2.end(); if(*it==3){ // l1.splice(it,l2); l1.splice(it,l2,first,last); } for(auto i:l1) cout<<i<<‘ ‘;//0 1 2 11 12 13 14 3 4 5 cout<<endl; l1.reverse(); for(auto i:l1) cout<<i<<‘ ‘;//5 4 3 14 13 12 11 2 1 0 cout<<endl; l1.sort(); for(auto i:l1) cout<<i<<‘ ‘;//0 1 2 3 4 5 11 12 13 14 cout<<endl; return 0; }
splice
public:
//將x接合於position之前
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(last!=first){
transfer(position,first,last);
}
}
merge
//merge()將x合並到*this身上,兩個list的內容都必須經過遞增排序
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();
//註意:前提是兩個鏈表都經過遞增排序
while(first1!=last1&&first2!=last2){
if(*first2<*first1){
iterator next=first2;
tranfer(first1,first2,++next);
first2=next;
}
else
++first1;
if(first2!=last2)
transfer(last1,first2,last2);
}
}
reverse
//reverse()內容逆置
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() //本函數采用quicksort(看代碼好像不是快排,而是歸並) 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作為輔助數據存放區 list<T,Alloc> carry; list<T,Alloc> counter[64]; int fill=0; while(!empty()){ carray.splice(carry.begin(),*this,begin()); int i=0; while(i<fill&&!counter[i].empty()){ counter[i].merge(carray); carray.swap(counter[i++]); } carray.swap(counter[i]); if(i==fill) ++fill; } for(int i=1;i<fill;++i){ counter[i].merge(counter[i-1]); } swap(counter[fill-1]); }
下面來解釋一下sort的實現,以21,45,1,30,52,3,58,47,22,59,0,58為例:
1、counter[0]:21 註:counter[i]存放2i+1個數,當達到第2i+1個數時,移動數據到counter[i+1]中
2、counter[0]:21,45 註:counter[0]元素已滿
counter0]:NULL
counter[1]:21,45
3、counter[0]:1
counter[1]:21,45
4、counter[0]:1,30 註:counter[0]元素已滿,利用merge合並counter[0]至counter[1]
counter[1]:21,45
counter[0]:NULL
counter[1]:1,30,21,45 註:counter[1]元素已滿,
counter[0]:NULL
counter[1]:NULL
counter[2]:1,30,21,45
......
最後得到:
counter[0]:58
counter[1]:0,59
counter[2]:NULL
counter[3]:1,3,21,30,47,45,52,58
再次歸並得到最後結果。
參考地址:https://blog.csdn.net/shoulinjun/article/details/19501811
list源碼4(參考STL源碼--侯捷):transfer、splice、merge、reverse、sort