SGI STL------------deque的特点

我们都知道在使用deque的时候,它是两端都可插入,取出;并且支持随机取数的一个容器;给人从表面上看起来,好像是一个连续线性空间;其实deque的内部实现上,它是一个分段连续线性空间

deque和Vector的最大差异,一在于deque允许于常数时间内对头端进行元素的插入或移除操作,(这里就是因为分段的原因,它只需要在这一小段进行操作,不像vector是整个区间向后移动);二在于deque没有所谓容量观念,因为它是动态地以分段连续空间组合而成,(于是就没必要想vector一样,弄一个capacity,来判断空间容量,以此来成倍扩容,移动)

就是由于分段连续空间,从而这里的迭代器就不像普通指针,其复杂度就会升高;

下面体会一下设计的分层思想

一、deque的中控器

我们知道,现在deque是用一块块连续的空间拼接而成,从而,如果一个迭代器走到了其中一块的尾端,那么它就需要跨到另一个段,因此这里就需要一个中控器,得记录每一块的地址,这样才能方便移动;

这里就是STL中大体的一个结构,可以从图中看出,其中控器是一个叫map的一块连续空间控制的;里面每个节点放置的是一块存储区的头节点;

template <class T,class Alloc=alloc,size_t BufSiz=0>
class deque{
public :
	typedef T value_type;
	typedef  value_type* pointer;
	...
protected:
	typedef pointer* map_pointer;
protected:
	map_pointer map;
	size_type map_size;

}

因此,map存的是一个地址,而它本身也是一个地址;


于是,我就在想,这要是让我接下来,粗略的去设计怎么移动,怎么放置数据,我应该怎么设计

我想的是,我的缓冲区里,固定同样大小段的尺寸,这样我就在map里面存放首地址,当取某个元素的时候,就计算一下在哪一个块,走多少步即可,而头部插入,我想的是想栈一样,放入缓存块的尾部,依次从尾部,向头部增长(很明显,这里我并没有想好,因为我的map放的是首地址,而头部插入我要是放在尾部,那你根本不知道第一个数据在哪?这样,我就需要多一个指针来维护地一个地址和最后一个地址,不过现在想一下,的确也可以)


接下来就是deque的两层设计,因为外表的整体连续,从而就需要一个指针来维护其跨块和在一个块内的移动,这就是

二、迭代器

//简单的表示
//这里利用first,last来控制一块的边界
//用node来进行下一块的,或者上一块的移动
template <class T>
struct __deque_iterator
{
	T *cur;		此迭代器指向缓冲区的当前元素
	T *first;	//此迭代器指向一块缓冲区的头部
	T *last;	//此迭代器指向一块缓冲区的尾部
	map_pointer node;	//指向管控中心
};

因此,有了迭代器,那么就可以实现元素的移动,比如operator++,operator--;operator-=等等;

三、deque的数据结构

template <class T>
class deque{
public:
	typedef T value_type;
	typedef value_type* pointer;
	typedef size_t size_type;

public:
	typedef __deque_iterator<T> iterator;

protected:
	typedef pointer* map_pointer;

protected:
	iterator start;
	iterator finish;

	map_pointer map;

	size_type map_size;
 
}

通过start 和 finish 来指向首尾元素的节点。(当然其中包含了它所在块的头和尾,和在map中的节点)

有了这些结构从而就可以实现比如:

public:
 	iterator begin() {return start;}
 	iterator end() {return finish;}

 	reference operator[](size_type n){
 		return start[difference_type(n)];
 	}

 	reference front()	{return *start;}
 	reference back(){
 		iterator tmp=finish;
 		--temp;
 		return *temp;
 		//这里为什么不使用return *(finish-1);
 		//因为这里并没有定义iterator-int的算子
 	}

最后,那么接下来就需要创建map和node了,以及push_back(),push_front()操作,这些都是逻辑操作,就不赘述;当然还有一下需要注意的问题,比如什么时候map中给的节点并不够了,那么就需要换一块连续的空间,来存储块的地址;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值