系列六 deque(二)

操作符重载

deque底层实际上是将元素在一段段内存中存储起来,然后每一段的起始地址是通过一个vector的数组进行管理的。为了实现逻辑上的连续,所以针对iterator的设计来说,是需要重载各种操作符的。
首先现在这里说一下接下来经常看到的一个self,这个定义是
typedef __deque_iterator self;

其实就是iterator的别称。

基本的函数

reference operator*() const{return *cur;}
pointer operator-> const{ return &(operator*());}

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

reference front(){return *start;}
reference back(){
	iterator tmp = finish;
	--tmp;
	return *tmp;
}

size_type size() const{return finish -start;}//这里需要重载运算符-
bool empty() const{return finish == start;}

在这里要强调的是size()这个函数,因为是要算所有的段中的元素,因此我们是需要重载-这个操作符的

重载‘-’

长度是有三部分组装成:队头的段中元素的个数、队列中的段的元素的个数、队尾的段中的元素的个数。

difference_type operator-(const self& x) const{
	return difference_type(buffer_size()) * (node - x.node  - 1) + (cur - first) + (x.last - x.cur);
	//cur-first表示deque最后一段的现有的元素
	//x.last-x.cur表示deque第一段的现有的元素
}

重载’++’/’–’

重载++只需要注意是否会跨段访问。

self& operator++(){
	++cur;
	if(cur == last){
		set_node(node + 1);//到下一个缓冲区
		cur = first;
	}
	return *this;
}

同理‘–’也要注意是否会跨段访问

self& operator--(){
	if(cur == first){
		set_node(node - 1);
		cur = last;
	}
	--cur;
	return *this;
}

两者唯一的区别就是对于++而言是沿着first->cur->last增长的;–是沿着last->cur->first增长的。

set_node的功能是在中央控制单元map_pointer控制节点,也就是控制存储段地址的空间。这里要注意一点的是,map_pointer底层虽然是vector,但是在扩容的时候有一点区别。vector一般扩容搬运元素的时候是从新开的空间的空间头开始的;但是因为deque是一个双向的,也就是有可能在头/尾加新的node。在这种情况下,我们在vector扩容,我们不应该是从新空间的头开始填充,而应该是从中间填充的,这样才可以保证deque的新节点插入的时候,是可以充分利用空间的。

void set_node(map_pointer new_node){
	node = new_node;
	first = *new_node;
	last = first + difference_type(buffer_size());
}

重载’+n’/’-n’

因为需要模拟随机访问的特性,因此需要重载所有的对指针进行‘+’或者‘-’.因为‘-’相当于‘+’个负数,因此我们只需要重载‘+’便可以完成上述的所有的功能的。调用‘+’实际上是通过重载‘+=’实现的。


self operator+(difference_type n) const{
	self tmp = *this;
	return tmp += n;
}
//重载+=
self& operator+=(difference_type n){
	difference_type offset = n + (cur - first);
	if(offset >= 0 && offset < difference_type(buffer_size())){
	//目标位置在同一个段里面
		cur += n;
	}else{
	//目标位置跨段了
		//找到需要跨越几个段
		difference_type node_offset = offset > 0 ? offset / difference_type(buffer_size()) 
		: - difference_type((-offset - 1) / buffer_size()) - 1; 
		//去中央控制器找相对应的node的入口
		set_node(node + node_offset);
		//移动到正确的位置
		cur = first + (offset - node_offset * difference_type( buffer_size() ));
	}
	return *this;
}

同理,-n只需要调用+(-n)就好了。因为在重载+=的时候,我们已经判断offset的正负决定是往哪个方向移动。

self operator-(){
	self tmp = *this;
	return tmp -= n;
}

self& operator-=(difference_type n){
	return *this += -n;
}

Reference

侯捷老师

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值