STL之deque(四)

	void push_back(const value_type& t)
	{
		// 最后缓冲区尚有两个(含)以上的元素备用空间
		if (finish.cur != finish.last - 1)
		{
			construct(finish.cur, t);     // 直接在备用空间上构造元素
			++finish.cur;     // 调整最后缓冲区的使用状态
		}
		// 容量已满就要新申请内存了
		else
			push_back_aux(t);
	}
// 只有当finish.cur == finish.last - 1 时才会被调用
// 也就是说,只有当最后一个缓冲区只剩下一个备用元素空间时才会被调用
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::push_back_aux(const value_type& t)
{
	value_type t_copy = t;
	reserve_map_at_back();
	*(finish.node + 1) = allocate_node();    // 配置一个新节点(缓冲区)
	__STL_TRY
	{
		construct(finish.cur, t_copy);         // 针对标的元素设值
		finish.set_node(finish.node + 1);      // 改变finish,令其指向新节点
		finish.cur = finish.first;             // 设定finish的状态
	}
	__STL_UNWIND(deallocate_node(*(finish.node + 1)));
}
 void reserve_map_at_back (size_type nodes_to_add = 1)
 {
        //  l= map + map_size ==最后的node之后一个越界的node
        //  l-finish.node -1 == 剩下的node个数
        //  nodes_to_add > l - finish.node -1 不需要重新分配内存
        if(nodes_to_add + 1 > map_size - (finish.node - map))
                    reallocate_map(nodes_to_add,false);//false表示在尾部重分配              
 }
//reallocate_map
template<class T,class Alloc,size_t BufSize>
void deque<T,Alloc,BufSize>::reallocate_map(size_type nodes_to_add,  bool add_at_front)
{
                
         size_type ole_num_nodes = finish.node - start.node + 1;     
         size_type new_num_nodes = ole_num_nodes + nodes_to_add;
                       
         map_pointer new_nstart;//T**类型
                       
         if(map_size > 2 * new_num_nodes)
         {  
             //node内存数量是 两倍的 新的node数量 时调用, 头尾总是pop时,会剩余大量node
                    
             /*
                  最后要使头尾剩下的可分配(未使用)的node数量一样
                  如果add_at_front = true new_nstart会多一个node节点
                  如果add_at_front = false new_nfinish会多一个node节点
                     
                  说到底 这个reallocate函数并不添加node,他的使命是确保有足够的
                  nodes给前面的aux函数使用
             */
              new_nstart = map + (map_size - new_num_nodes) / 2
                    + (add_at_front ? nodes_to_add : 0);
                    
              //防止覆盖问题
               if(new_nstart < start.node)
                     copy(start.node , finish.node + 1, new_nstart);
               else
                     copy_backward(start.node, finish.node + 1, new_nstart + ole_num_nodes);
                    
          }
          else
          {         
               //剩下的没有两倍就 重新分配一块nodes内存
               //新的缓存区起码要留map_size+2 的大小
                size_type new_map_size = map_size + max(map_size, nodes_to_add) + 2;    
                map_pointer new_map =map_allocator::allocate(new_map_size);
                    
                //同上
                new_nstart = new_map + (new_map_size - new_num_nodes) / 2
                    + (add_at_front ? nodes_to_add : 0);
                    
                copy(start.node, finish,node +1, new_nstart);
                map_allocator::deallocate(map,map_size);
                    
                map=new_map;
                map_size = new_map_size;
                    
           }
                
           start.set_node(new_nstart);
           finish.set_node(new_nstart + ole_num_nodes);
                
 }
void push_front(const value_type& t)
{
       if (start.cur != start.first)      // 第一缓冲区尚有备用空间
       {
		construct(start.cur - 1, t);   // 直接在备用空间上构造元素
		--start.cur;     // 调整第一缓冲区的使用状态
	}
	else    // 第一缓冲区已无备用空间
		push_front_aux(t);
}
// Called only if start.cur == start.first.
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::push_front_aux(const value_type& t)
{
	value_type t_copy = t;
	reserve_map_at_front();
	*(start.node - 1) = allocate_node();
	__STL_TRY
	{
		start.set_node(start.node - 1);        // 改变start,令其指向新节点
		start.cur = start.last - 1;            // 设定start的状态
		construct(start.cur, t_copy);          // 针对标的元素设值
	}
	catch(...)
	{
		start.set_node(start.node + 1);
		start.cur = start.first;
		deallocate_node(*(start.node - 1));
		throw;
	}
}

        pop_back和pop_front函数讲解:

//pop_back
void pop_back()
{
        if(finish.cur != finish.first)
        {
              --finish.cur;
              destroy(finish.cur);
         }
         else
                    
               pop_back_aux();
                
 }
            
//pop_back_aux
template<class T,class Alloc,size_t BufSize>
void deque<T,Alloc,BufSize>::pop_back_aux()
{
        //释放finish的缓存,使finish指向前一个node末尾
        //deallocate_node(pointer n){ data_allocator::deallocate(n,buffer_size());}
        deallocate_node(finish.first);
        finish.set_node(finish.node - 1);
        finish.cur = finish.last -1;
        destroy(finish.cur);
}
            
//pop_front 
void pop_front()
{
        if(start.cur != start.last -1 )
        {
              destroy(start.cur)
              ++start.cur;
         }
         else      
              pop_front_aux();
}
         
//pop_front_aux
template<class T,class Alloc,size_t BufSize>
void deque<T,Alloc,BufSize>::pop_front_aux()
{
         destroy(start.cur);
         deallocate_node(start.first);
         start.set_node(start.node +1);
         start.cur = start.first;
}

        clear函数讲解:

template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::clear()
{
	// 以下针对头尾以外的每一个缓冲区
	for (map_pointer node = start.node + 1; node < finish.node; ++node)
	{
		// 将缓冲区内的所有元素析构
		destroy(*node, *node + buffer_size());
		// 释放缓冲区内存
		data_allocator::deallocate(*node, buffer_size());
	}

	if (start.node != finish.node)   // 至少有头尾两个缓冲区
	{
		destroy(start.cur, start.last);  // 将头缓冲区的目前所有元素析构
		destroy(finish.first, finish.cur);  // 将尾缓冲区的目前所有元素析构
		// 以下释放尾缓冲区。注意:头缓冲区保留
		data_allocator::deallocate(finish.first, buffer_size());
	}
	else   // 只有一个缓冲区
		destroy(start.cur, finish.cur);   // 将此唯一缓冲区内的所有元素析构
		// 注意:并不释放缓冲区空间,这唯一的缓冲区将保留

	finish = start;   // 调整状态
}

        erase函数讲解:

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

        insert相关函数:

iterator insert(iterator position, const value_type& x)
{
         if(position.cur == start.cur)
         {
                push_front(x);
                return start;
         }
         else if(position.cur == finish.cur)
         {
                push_back(x);
                iterator tmp = finish;
                --tmp;
                return tmp;
         }
         else
         {
                return insert_aux(position,x);
          }
 }

template <class T, class Alloc, size_t BufSize>
typename deque<T, Alloc, BufSize>::iterator
deque<T, Alloc, BufSize>::insert_aux(iterator pos, const value_type& x)
{
	difference_type index = pos - start;   // 插入点之前的元素个数
	value_type x_copy = x;

	// 前面的时候用的移位操作, 这里怎么不用了呢^_^?
	if (index < size() / 2)    // 如果插入点之前的元素个数比较少
	{
		push_front(front());       // 在最前端加入与第一元素同值的元素
		iterator front1 = start;   // 以下标示记号,然后进行元素移动
		++front1;
		iterator front2 = front1;
		++front2;
		pos = start + index;
		iterator pos1 = pos;
		++pos1;
		copy(front2, pos1, 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;
}
deque完结!
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值