STL的List节点
STL的List节点结构如下
struct node{
T data;
node *prev;
node *next;
list<T> *container;
};
显然是List是一个双向链表。
STL的List迭代器
list不再像vector一样能以普通指针当做迭代器,因为其节点不保证在连续空间内,list的迭代器必须有能力指向list的结点,并有能力进行递增,递减,取值,成员存取等操作。
由于list是一个双向链表,迭代器必须具有前移和后移的能力,所以list提供的是Bidirectional Iterator.
list有个重要的性质:插入和接合操作都不会造成原有的list迭代器失效,这在vector是不成立的,因为vector的插入可能造成记忆体重新配置,导致原有的迭代器全部失效。甚至List的元素删除操作也只有指向被删除的那个迭代器失效,其他迭代器不受任何影响。
迭代器设计如下:
template<class T>
struct listIterator :public iterator<bidirectional_iterator_tag, T>{
template<class T>
friend class list;
public:
typedef node<T>* nodePtr;
nodePtr p;
public:
explicit listIterator(nodePtr ptr = nullptr) :p(ptr){}
listIterator& operator++(){
p=(nodeptr)(p->next);
return *this;
}
listIterator operator++(int){
self temp=*this;
++*this;
return temp;
}
listIterator& operator --(){
p=(nodeptr)(p->prev);
return *this;
}
listIterator operator --(int){
self temp=*this;
--*this;
return temp;
}
T& operator *(){ return p->data; }
T* operator ->(){ return &(operator*()); }
};
list的数据结构
list不仅是双向链表还是一个环状双向链表,所以他需要一个指针,便可以完整表现整个链表。
template<class T,class Alloc=alloc>
class list{
protect:
typedef _list_node<T> list_node;
public:
typdef list_node *link_type;
protect:
link_type node;//只要一个指针便可表示整个环状双向链表
};
如果让指针node指向可以置于尾端的一个空白点,node便能符合STL“前闭后开”的区间要求,成为last迭代器,如下图
这样下面几个函数便可以轻易完成。
iterator begin(){return (link_type)((*node).next);}
iterator end(){return node;}
bool empty(){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的元素操作
list的插入操作和移除操作较为重要,再加上list的操作很多,所以只挑这两个来说。
//插入一个节点作为头节点
void push_front(const T &x){insert(begin(),x);}
//插入一个节点作为尾节点
void push_back(const T &x){insert(end(),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);
return iterator(next_node);
}
//移除头节点
void pop_front(){erase(begin());}
//移除尾节点
void pop_back(){
iterator temp=end();
earse(--temp);
}
//清除所有节点
template<class T,class Alloc>
void list<T,Alloc>::clear(){
link_type cur=(link_type)node->next;//begin()
while(cur!=node){
link_type temp=cur;
cur=cur->next;
destroy_node(temp);
}
node->prev=node;
node->next=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==value)erase(first);
first=next;
}
}
list内部提供一个所谓的迁移操作(transfer),将某连续范围内的元素迁移到某个特定位置前。
//将[first,last)内的所有元素移动到position前
void transfer(iterator position,iterator first,iterator last){
if(position!=last){
(*(link_type((*last.node).prev))).next=position.node;
(*(link_type((*first.node).prev))).next=last.node;
(*(link_type((*position.node).prev))).next=first.node;
link_type temp=link_type((*position.node).prev);
(*position.node).prev=(*last.node).prev;
(*last.node).prev=(*first.node).prev;
(*first.node).prev=temp;
}
}