1. 程式人生 > >list源碼4(參考STL源碼--侯捷):transfer、splice、merge、reverse、sort

list源碼4(參考STL源碼--侯捷):transfer、splice、merge、reverse、sort

bubuko uniq view col 進行 https out stl算法 details

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
namespace 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; }
View Code

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