List使用一個doubly linked list(雙向對列)來保存元素,相較於Vector的線性空間,List就顯的複雜的多,它的好處是每次插入或刪除一個元素,就配置或釋放一個元素空間。對於任何位置的元素的插入或刪除,List永遠是常數時間。node
list自己和list節點是不一樣的結構,須要分開設計。如下是STL list的節點(node)結構:c++
template <class T> struct __list_node{ typedef void* void_pointer; void_pointer prev; void_pointer next; T data; }
因爲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; } }
SGI list 不只是一個雙向鏈表,並且仍是一個環裝雙向鏈表。因此它只須要一個指針,即可以完整表現整個鏈表:post
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())}
list缺省使用alloc做爲空間配置器,並據此另外定義了一個list_node_allocator.this
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; }
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; } }