STL之list

5 篇文章 0 订阅

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;
    }
}

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值