Deuqe

来源:互联网 发布:mac high sierra 编辑:程序博客网 时间:2024/06/05 00:54
deque是一种双向开口的连续线性空间,vector是单向开口的连续线性空间。
deque与vector区别:1、deque是双向开口的连续节点,2、deque没有所谓容量概念。
deque是分段连续的空间,由一段一段的定量连续空间构成,
deque类源码:
template <class T>
class deque{
public:
    typedef T value_type;
    typedef value_type* pointer;

protected:
    typedef pointer* map_pointer;
    map_pointer map;    //指向map,map是块连续空间,其内的每个元素都是一个指针(称为节点),指向一块缓冲区
    size_type map_size;    //map中可容纳的指针数

    //    数据成员
protected:
    iterator start;
    iterator finish;
    map_pointer map;
    size_type map_size;

};

deque的迭代器,具体实现下图可以看出:

迭代器的几个关键行为:
当指针的加减等运算,遇到缓冲区边缘,就需要调用ser_node()跳一个缓冲区:
void set_node(map_pointer new_node){        //注意:没有对cur进行初始化,所以跳转一个缓冲区时不要忘了设置cur节点
    node=new_node;
    first=*new_node;
    last=first+difference_type(buffer_size());
}
//各种运算符的重载
difference_type operator-(const self& x) const{
    return difference_type(buffer_size())*(node-x.node-1)+(cur-first)+(x.last-x.cur);
}
//自增与自减同理
self& operator++(){
    ++cur;
    if(cur==last){
        set_node(node+1);
        cur=first;
    }
    return *this;
}
//自增后置式,标准写法——先运算,后自增
self operator++(int){
    self tmp=*this;
    ++*this;
    return tmp;
}
//实现随机存取,迭代器直接跳跃n个距离
self& operator+=(different_type n){
    different_type offset=n+(cur-first);
    if(offset>=0&&offset<different_type(buffer_size())){    //在同一缓冲区
        cur+=n;
    }else{    //不在同一缓冲区内
        different_type node_different=offset>0?offset/buffer_size():-(-offset-1)/buffer_size()-1;
        set_node(node_different);
        cur=first+(offset-node_different*buffer_size());
    }
    return *this;
}
//加法操作
self operator+(difference_type n) const{
    self tmp=*this;
    return tmp+=n;
}
deque的数据结构:
begin()    end()    operator[]    front()    back()    size()    empty()    略
push_back:
void push_back(const value_type& t){
    if(finish.cur!=finish.last-1){    //最后缓冲区还有两个及以上元素空间备用,可直接插入
        construct(finish.cur,t);
        ++finish.cur;
    }
    else    //新增一块新的缓冲区
        push_back_aux(t);
}
void push_back_aux(const value_type& t){
    value_type t_copy=t;
    reserve_map_at_back();        //若map的大小不够用,则需要换一个更大的map空间(配置更大的、拷贝原来的、释放原来的)
    *(finish.node+1)=allocate_node();        //配置一个新的节点,即新缓冲区
    {
        construct(finish.cur, t_copy);
        finish.set_node(finish.node+1);
        finish.cur=finish.first;
    }
}
push_front同理,首先判断start.cur和start.first是否相等,即是否需要增加一块缓冲区,如果不需要,可直接插入,否则,新增一块缓冲区并配置节点,改变start的值。
pop_back:    //pop_back、pop_front与push_back、push_front并无太大差异,不过就是删除或插入节点,需要重新分配或者释放缓冲区
void pop_back(){
    if(finish.cur!=finish.first){    //无需释放缓冲区
        --finish.cur;
        destory(finish.cur);
    }
    else
        pop_back_aux();        //需要释放缓冲区
}
void pop_back_aux(){
    deallocate_node(finish.first);    //释放最后一个缓冲区
    finish.set_node(finish.node-1);    //跳转缓冲区
    finish.cur=finish.last-1;        
    destory(finish.cur);        //将该元素析构
}
pop_front与pop_back无异,前面判断的是start.cur==start.last-1;
erase:删除某个特定位置的元素,时间复杂度为O(n),删除之后需要将后面元素前移,并释放最后一个元素。
iterator erase(iterator pos){     //返回删除元素后的
    iterator next=pos;
    ++next;
    difference_type index=pos-start;        //判断该清除节点离头结点近还是离尾节点近,然后选择移动少的那部分
    if(index<(size()-1)){
        copy_backward(start, pos, next);
        pop_front();
    }
    else{
        copy(next, finish, pos);
        pop_back();
    }
    return start+index;    //此时next指针和pos指针失效,因此返回start+index,删除元素后元素的迭代器。
}
deque erase(iterator first, iterator last){......}  //删除[first,last)间的元素。
insert:    //时间复杂度O(n),需要前移或后移其余元素
iterator insert(iterator pos, const value_type& x){
    if(pos.cur==first.cur){    //插入点是deque的最前端,交给push_front
        push_front(x);
        return first;
    }
    else if(pos.cur==finish.cur){        //插入点是deque的最后端,交给push_back
        push_back(x);
        iterator tmp=finish.cur;  //返回的迭代器要指向插入的节点,而finish指向最后一个节点后面的节点,因此需要向前移一步
        --tmp;
        return tmp;
    }
    else{        //在deque中间位置插入
        return insert_aux(pos, x);
    }
}
deque insert_aux(iterator pos, const value_type& x){
    difference_type index=pos-first;    //计算插入节点与头结点的距离,选择较小部分进行前移或后移
    value_type x_copy=x;
    if(index<size()/2) {
        push_front(front());
        iterator front1=start;
        ++front1;
        iterator front2=front1;
        ++front2;
        pos=front+index;
        iterator pos1=pos;
        ++pos1;
        copy(front2, pos2, front1);
    }
    else{
        push_back(back());
        iterator back1=finish;
        --back1;
        iterator back2=back1;
        --back2;
        pos=start+index;
        copy_backward(pos, back2, back1);
    }
    *pos=x_copy;
    return pos;
}

















0 0
原创粉丝点击