SGI STL值List

youngwb發表於2019-05-11

1.概述

List使用一個doubly linked list(雙向對列)來儲存元素,相較於Vector的線性空間,List就顯的複雜的多,它的好處是每次插入或刪除一個元素,就配置或釋放一個元素空間。對於任何位置的元素的插入或刪除,List永遠是常數時間。

2.list的節點

list本身和list節點是不同的結構,需要分開設計。以下是STL list的節點(node)結構:

template <class T>
struct __list_node{
   typedef void* void_pointer;
   void_pointer prev;
   void_pointer next;
   T data;
 }

3.list的迭代器

由於STL List是一個雙向連結串列,迭代器必須具備前移、後移的能力,所以list提供的是Bidirectional Iterators
list 有一個重要的性質:插入操作(insert)和接合操作(splice)都不會造成原有list迭代器失效。這在vector是不成立的,因為vector的插入操作可能會造成空間的重新配置,導致原有迭代器的全部失效。甚至list的刪除(erase)操作也只有“指向被刪除元素”的那個迭代器失效,其他迭代器不收任何影響。

以下是list迭代器的設計:(只列出部分)

template<class T,class Ref,class Ptr>
struct __list_iterator{
    typedef __list_iterator<T,T&,T*> iterator;
    typedef __list_iterator<T,Ref,Ptr> self;
    
    typedef bidirectioanal_iterator_tag iterator_category;
    typedef T value_type;
    typedef Ptr pointer;
    typedef Ref referrence;
    typedef __list_node<T>* link_type;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;
    
    link_type node;
    
    __list_iterator(link_type x):node(x);
    __list_iterator(){}
    __list_iterator(const iterator& x):node(x.node){}
    
    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;
    }
 }

4.list的資料結構

SGI list 不僅是一個雙向連結串列,而且還是一個環裝雙向連結串列。所以它只需要一個指標,便可以完整表現整個連結串列:

template <class T,class alloc=Alloc>
class list{
protected:
    typedef list_node<T> node;
public:
    typedef list_node* link_type;
protected:
    link_type node;
}

iterator begin(){ return (link_type)((node*).next);}  //return link_type,使用iterator(link_type)建構函式返回一個iterator;
iterator end(){return node;}

bool empty() const {return node->next==node;}
size_type size() const{
    size_type result=0;
   distance(begin(),end(),result);
   return result;
 }
 
 reference front() {return *begin()}
 reference back() {return *(--end())}

5.list的構造與記憶體管理

list預設使用alloc作為空間配置器,並據此另外定義了一個list_node_allocator.

template <class T,class Alloc=alloc>
class list{
protected:
    typedef __list_node<T> list_node;
   typedef simple_alloc<list_node,Alloc> list_node_allocator;
 }

list_node_allocator(n)表示配置n個節點空間。以下四個函式分別用來配置、釋放、構造、銷燬一個節點:

protected:
    //配置一個節點並傳回
    link_type get_node() {return list_node_allocator::allocate();}
   //釋放一個節點
   void put_node(lingk_type p){ list_node_allocator::deallocate();}
   
   //產生(配置並構造)一個節點,帶有元素值
   link_type create_node(const T& x){
          link_type p=get_node();
       construct(&p->data,x);
       retrurn p;
   }
   
   //銷燬(析構並釋放)一個節點
   void destroy_node(link_type p){
           destory(&p->data);
       put_data(p);
    }
 
public:
    list(){ empty_initialize(); }
protected:
    void empty_initialize(){
         node=get_node();
       node_next=node;
       node_prev=node;
    }
    
    void push_back(const T&) {insert(end(),x);}
    
    iterator insert(iterator position,const T& x){
        link_type tmp=create_node(x);//產生一個節點;
       tmp->next=position.node;
       tmp->prev=position.node->prev;
       (link_type(psition.node->prev))->next=tmp;
       postion.node->prev=tmp;
       return tmp;
    }    

6.list的元素操作

void push_back(const T& x){insert(end(),x);}
void psuh_pront(const T& x){insert(begin(),x);}

//移除迭代器position所指節點
iterator 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;
   destroy_node(position.node);
   return iterator(next_node);
}

//移除頭結點
void pop_front()    { erase(begin());}
//移除尾節點
void pop_back(){
    iterator tmp=end();
   erase(--tmp);
 }
 
//清除所有節點(整個連結串列)
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;
       destroy(tmp);
   }
   node->next=node;
   node->prev=node;
}

//將數值為value的所有元素移除
template <class T,class Alloc>
void list<T,Alloc>::remove(const T& value){
    iterator first=begin();
   iterator last=end();
   while(first!=last){
           iterator next = first;
       ++next;
       if(*first==next) 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(*first == *next)
              erase(next);
       else
               first=next;
       next=first;
    }
 }