STL學習_stl_list.h_源碼分析

stl_list.h中有幾個函數自己覺得比較重要,transfer()  merge()  sort()

#ifndef _SGI_STL_INTERNAL_LIST_H
#define _SGI_STL_INTERNAL_LIST_H

//list迭代器結構
//不同的容器往往要給容器設置符合自己的迭代器,list的迭代器類型是雙向迭代器
//list的迭代器必須有能力進行遞增,遞減,取值,成員存取等操作
template<class T, class Ref, class Ptr>
struct __list_iterator{
    typedef __list_iterator<T, T&, T*> iterator;
    typedef __list_iterator< T, const T&, const T*> const_iterator;
    typedef __list_iterator<T, Ref, Ptr> self;
    //這樣寫的目的是,爲了否和規範,自行開發的迭代器因該提供五個內嵌相應型別,
    //以利於traits萃取。
    typedef bidirectional_iterator_tag iterator_category;
    typedef T value_type;
    typedef Ref reference;
    typedef Ptr pointer;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;
    typedef __list_node<T>* link_type;
    //迭代器內部指針node指向list的節點
    link_type node;
    //list迭代器的構造函數
    __list_iterator(){}
    __list_iterator(link_type x):node(x){}
    __list_iterator(const iterator& x):node(x.node){}

    bool operator==(const self& x)const
    {
        return node == x.node;
    }
    bool operator!=(const self& x)const
    {
        return node != x.node;
    }
    //對迭代器取值,取的是節點的數據值
    reference operator*() const
    {
        return (*node).data;
    }
    //對迭代器的成員存取
    pointer operator->()const
    {
        return &(operator*());
    }
    //迭代器前進一個節點(對前置++的符號重載)
    self& operator++()
    {
        node = (link_type)((*node).next);
        return *this;        
    }
   //(對後置++的符號重載)
    self& operator++(int)
    {
        self tmp = *this;
        ++*this;
        return tmp;
    }
    //迭代器後退一個節點
    self& operator--()
    {
        node = (link_type)((*node).prev);
        return *this;
    }
    self& operator--(int)
    {
        self tmp = *this;
        --*this;
        return tmp;
    }
    
};
//list的節點結構
template<class T>
struct __list_node{
    typedef void* void_pointer;
    void_pointer next;
    void_pointer perv;
    T data;
};

//list的結構
//list缺省使用alloc第二空間配置器
template<class T, class Alloc=alloc>
class list{
protected:
    typedef __list_node<T> list_node;
    //定義的list_node_allocator這個專屬空間配置器,方便以節點大小爲配置單位
    typedef simple_alloc<list_node, Alloc> list_node_allocator;
    typedef void* void_pointer;
public:
    typedef T value_type;
    typedef value_type* pointer;
    typedef const value_type* const_pointer;
    typedef value_type& reference;
    typedef const value_type& const_reference;
    typedef list_node* link_type;
    size_t size_t size_type;
    typedef ptrdiff_t difference_type;
public:
    typedef __list_iterator<T, T&, T*> iterator;
    typedef __list_iterator<T, const T&, const T*> const_iterator;
    //逆置迭代器
    typedef reverse_iterator<const_iterator> const_reverse_iterator;
    typedef reverse_iterator<iterator> reverse_iterator;
public:
    //list提供的接口
    iterator begin(){return (link_type)((*node).next);}
    const_iterator begin()const{return (link_type)((*node).next);}
    iterator end(){return node;}
    const_iterator end()const {return 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());
    }
    bool empty()const{return node->next == node;}
    size_type size()const{
        size_type result = 0;
        distance(begin(), end(), result);
        return result;
    }
    size_type max_size()const{
        return size_type(-1);
    }
    reference front(){return *begin();}
    const_reference front()const{return *begin();}
    reference back(){return *(--end());}
    const_reference back(){return *(--end());}

    void swap(list<T, Alloc>&x)
    {
        __STD::swap(node, x.node);
    }

    void clear();
    iterator erase(iterator position);
    iterator erase(iterator first, iterator last);
    //重置list的大小
    void resize(size_type new_size, const T& x);
    //將數值爲value的元素全部移除,注意區分不同容器的remove的用法不同
    void remove(const T& x);
    //移除數值相同的連續元素
    void unique();
    void push_front(const T& x){insert(begin(), x);}
    void push_back(const T& X){insert(end(), x);}
    void pop_front(){erase(begin());}
    void pop_back()
    {
        iterator tmp = end();
        erase(--tmp);
    }
    //將兩個鏈表接合,其實是transfer()的封裝
    void splice(iterator position, list& x)
    {
        if(!empty()){
            transfer(position, x.begin(), x.end());
        }
    }
    //逆置鏈表,就是按順序將list的節點接合到鏈表的begin()位置
    void reverse();
    //鏈表排序
    void sort();
    //將兩個有序鏈表接合並且排序
    void merge(list& x);
public:
    //list鏈表的構造函數的重載有5種
    list(){empty_initialize();}
    list(size_type n, const T& value){fill_initialize(n, value);}
    list(int n, const T& value){fill_initialize(n, value);}
    list(long n, const T& value){fill_initialize(n, value);}
    explicit list(size_type n){fill_initialize(n, T());}

    ~list()
    {
        clear();
        put_node(node);
    }

public:
    //insert函數的重載
    iterator insert(iterator position, const T& x)
    {
        link_type tmp = create_node(x);
        tmp->next = position.node;
        tmp->prev = position.node->prev;
        (link_type(position.node->prev))->next = tmp;
        position.node->prev = tmp;
        return tmp;
    }
    void insert(iterator pos, size_type n, const T& x);
    void insert(iterator pos, int n, const T& x)
    {
        insert(pos, (size_type)n , x);
    }
    void insert(iterator pos, long n, const T& x)
    {
        insert(pos, (size_type)n, x);
    }
    void insert(iterator position, InputIterator first, InputIterator last);
protected:
    //產生一個空鏈表
    void empty_initialize()
    {
        node = get_node();
        node->next = node;
        node->prev = node;
    }
    //填充鏈表
    fill_initialize(size_type n, const T& value)
    {
        empty_initialize();
        insert(begin(), n, value);
    }
    //配置一個節點僅僅是申請一個節點大小的空間
    link_type get_node()
    {
        return list_node_allocator::allocate();
    }
    //配置並且構造一個節點
    link_type create_node()
    {
        link_type p = get_node();
        construct(&p->data, x);
        return p;
    }
    //釋放一個節點
    void put_node(link_type p)
    {
        return list_node_allocator::deallocate(p);
    }
    //釋放並且析構一個節點
    void destory_node(link_type p)
    {
        destory(&p->data);
        put_node(p);
    }
protected:
    //將[first, last)內部的所有元素移動到position之前
    //這個內置的遷移函數很重要
    //分爲7步
    void transfer(iterator position, iterator first, iterator last)
    {
        //如果不是在尾部插入
        if(position != last){
            //(1)將插入範圍的最後的元素的next指針指向要插入的位置position上
            (*(link_type((*last.node).prev))).next = position.node;
            //(2)將第二個鏈表的斷開的位置的next指針指向另一端斷開的位置
            (*(link_type((*first.node).prev))).next = last.node;
            //(3)將第一個鏈表的插入位置的前驅的next指針指向要插入範圍的起始位置
            (*(link_type((*position.node).prev))).next = first.node;
            //(4)讓tmp指向插入位置的前驅節點
            iterator tmp = link_type((*position.node).prev);
            //(5)讓插入位置position的next指針指向插入範圍的結束位置
            (*positon.node).prev = (*last.node).prev;
            //(6)第二個鏈表的斷開位置的prev指針指向第二個鏈表的前面的斷開位置
            (*last.node).prev = (*fist.node).prev;
            //(7)讓插入範圍的起始位置的prev指針指向第一個鏈表的插入位置position的前驅節點
            (*first.node).prev = tmp;
        }
    }

};

template<class T, class Alloc>
void list<T, Alloc>::insert(iterator position, size_type n, const T& x)
{
    for( ; n > 0; --n){
        insert(position, x);
    }
}

template<class T, class Alloc>
void list<T, Alloc>::insert(iterator position, const T* first, const T* last)
{
    for( ; first != last; ++first){
        insert(position, *first);
    }
}

template<class T, class Alloc>
void list<T, Alloc>::clear()
{
    link_type cur = (link_type)node->next;
    while(cur != node){
        link_type tmp = cur;
        cur = (link_type)cur->next;
        destory_node(tmp);
    }
    //恢復node的原始狀態也就是空鏈表狀態
    node->next = node;
    node->perv = node;
}

template<class T, class Alloc>
iterator list<T, Alloc>::erase(iterator position)
{
    link_type next_node = link_type(position.node->next);
    link_type prev_node = link_type(position.node->prev);
    prev_node->next = next_node;
    next_node->prev = prev_node;
    destory_node(position.node);
    return iterator(next_node);
}

template<class T, class Alloc>
iterator list<T, Alloc>::erase(iterator first, iterator last)
{
    while(first != last){
        erase(first++);
        return last;
   }
}

template<class T, class Alloc>
void list<T, Alloc>::resize(size_type new_size, const T& x)
{
    iterator i = begin();
    size_type len = 0;
    for( ; i != end() && len < new_size; ++i){
        ++len;
    }
    if(len == new_size){
         erase(i, end());   
    }
    else{
         insert(end(), new_size-len, x);
    }
}

template<calss T, class Alloc>
void list<T, Alloc>::remove(const T& x)
{
    iterator first = begin();
    iterator last = end();
    while(first != last){
        iterator next = first;
        ++next;
        if(x == *first){
            erase(first);
        }
        first = next;
    }
}


template<class T, class Alloc>
void list<T, Alloc>::unique()
{
    iterator first = begin();
    iterator last = end();
    //空鏈的話直接退出
    if(first == last){
        return ;
    }
    iterator next = first;
    //一個一個遍歷
    while(++next != last){
        if(*next == *first){
            erase(next);
        }else{
            first = next;
        }
        next = first;
    }
}

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;
        //在begin()位置插入[old, first)範圍內的數值
        transfer(begin(), old, first);
    }
}
//整體思想是:讓兩個迭代器分別指向第一個第二個有序鏈表,對兩個鏈表進行遍歷
//如果第二個迭代器指向的節點小於第一個迭代器指向的節點則進行插入操作,如果
//不符合條件則繼續增加第一個迭代器直到找到那個比第二個迭代器大的節點位置進
//型插入操作並移動第二個迭代器,就這樣重複進行判斷
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;
           transfer(first1, first2, ++next)
           first2 = next;
        }else{
           ++first1;
        }
        
    }
    //如果第二個鏈表還沒有遍歷完,則直接把剩下的節點直接插入到第一個鏈表的後面即可
    if(first2 != last2){
        transfer(last1, first2, last2);
    }
}
//list不能使用STL的算法sort(),必須使用自己的排序算法,因爲STL的排序算法只接受

//RamdonAccessIterator類型的迭代器

//這裏採用的是quick sort

//sort()的大致思想:例如排序的鏈表是21,45,1,30,52,3,58,47,22,59,0,58

//那麼先放入第一個節點21   counter[0]:21   

//然後放入第二個節點45,放入之前要進行merge()排序      counter[0]:21, 45  

//放入第三個節點但是counter[0]最大隻能存放兩個節點,所以將counter[0]的所有節點放入counter[1]中

//則counter[0]:1     counter[1]21, 45

//放入第四個節點30, 放入之前要進行merge()排序  counter[0]1, 30    counter[1]21, 45

//放入第五個節點52,由於counter[0]以滿,則將所有節點放入counter[1]中,放之前要進行merge()排序

//即counter[0]:52  counter[1]1, 21, 30, 45就這樣不停的輪詢
template<class T, class Alloc>
void list<T, Alloc>::sort()
{
    if(node->next == node || link_type(node->next->next == node)){
        return ;

    }

    //carry  counter[64]這些新的list作爲中介數據存放區

    list<T, Alloc> carry;

    //這裏的counter[64]存放64個元素的數組,是用來做中轉的存放區的
    list<T, Alloc> counter[64];
    int fill = 0;
    while(!empty()){
        carry.splice(carry.begin(), *this, begin());
        int i = 0;
        while(i < 0 && !counter[i].empty()){
            counter[i].merge(carry);
            carry.swap(counter[i++]);
        }
        carry.swap(counter[i++]);
        if(i == fill){
            ++fill;
        }
    }
    for(int i = 0; i < fill; ++i){
        counter[i].merge(counter[i - 1]);
    }
    swap(counter[fill - 1]);
}
#endif

比如我們的list裏有如下幾個需要排序的元素:21,45,1,30,52,3,58,47,22,59,0,58。

排序的時候怎麼做,我們先定義若干中轉list在上述代碼中定義了64個元素的數組

list<_Tp, _Alloc> __counter[64]; 其中裏邊存什麼呢?他們都是用來中轉用的

__counter[0]裏存放2(0+1)次方個元素
__counter[1]裏存放2(1+1)次方個元素
__counter[2]裏存放2(2+1)次方個元素
__counter[3]裏存放2(3+1)次方個元素,依次類推

 

那又是怎麼個存放方法呢?一個指導原則就是當第i個元素即__counter[i]的內容個數等於2(i+1)次方時,就要把__counter[i]的數據轉移給__count[i+1]。

具體過程如下:

取出第1個數21,放到__counter[0]裏,這時__counter[0]裏有一個元素,小於2,繼續

__counter[0]: 21

__counter[1]: NULL

取出第2個數45,放到__counter[0]裏(不是簡單的放,而是排序放,類似兩個list做merge),這時__counter[0]裏有2個元素了,需要把這兩個元素轉移到__counter[1].

__counter[0]: NULL

__counter[1]: 21,45

取出第3個數1,放到__counter[0]裏,__count[0]與__count[1]都小於規定個數

__counter[0]: 1

__counter[1]: 21,45

取出第4個數30,放到__counter[0]裏,這時__counter[0]的個數等於2了,需要轉移到__counter[1]裏

__counter[0]: NULL

__counter[1]: 1,21,30,45

但這時__counter[1]裏的個數又等於4了,所有需要把__counter[1]的值轉移到__counter[2]裏,

__counter[0]: NULL

__counter[1]: NULL

__counter[2]: 1,21,30,45

然後取出52,放入__counter[0]

__counter[0]: 52

__counter[1]: NULL

__counter[2]: 1,21,30,45

然後取出3,放入__counter[0]

__counter[0]: 3,52

__counter[1]: NULL

__counter[2]: 1,21,30,45

這時候需要轉移

__counter[0]: NULL

__counter[1]: 3,52

__counter[2]: 1,21,30,45

然後取58

__counter[0]: 58

__counter[1]: 3,52

__counter[2]: 1,21,30,45

然後取47

__counter[0]: 47,58

__counter[1]: 3,52

__counter[2]: 1,21,30,45

需要轉移

__counter[0]: NULL

__counter[1]: 3,47,52,58

__counter[2]: 1,21,30,45

還需要轉移

__counter[0]: NULL

__counter[1]: NULL

__counter[2]: 1,3,21,30,47,45,52,58

還需要轉移

__counter[0]: NULL

__counter[1]: NULL

__counter[2]: NULL

__counter[3]: 1,3,21,30,47,45,52,58

然後再取59

__counter[0]: 59

__counter[1]: NULL

__counter[2]: NULL

__counter[3]: 1,3,21,30,47,45,52,58

然後取0

__counter[0]: 0,59

__counter[1]: NULL

__counter[2]: NULL

__counter[3]: 1,3,21,30,47,45,52,58

需要轉移

__counter[0]: NULL

__counter[1]: 0,59

__counter[2]: NULL

__counter[3]: 1,3,21,30,47,45,52,58

最後取58

__counter[0]: 58

__counter[1]: 0,59

__counter[2]: NULL

__counter[3]: 1,3,21,30,47,45,52,58



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章