这个deque看的我真是累。问题太多了,所以因此打算换一个看。而且后面的map和set也不全,后面看似乎是基于AVL而不是RBT实现的,所以换一个。作者还是很厉害的,毕竟让我自己写,目前水平肯定写不出来。但是吐槽还是要吐的
deque.h
#ifndef _DEQUE_H_
#define _DEQUE_H_
#include "Allocator.h"
#include "Iterator.h"
#include "ReverseIterator.h"
#include "Utility.h"
/*deque的实现较为复杂,因为是双向开口,所以涉及到内存分配,如何让他表现的像一个双向开口
deque通过一个地址数组的指针map_来实现。deque每次申请内存是申请一个大小为mapSize_的数组,这个数组里面放的是迭代器指针
这个deque的设计跟《STL源码剖析》小处有不同。二者deque的成员变量都一样,deque两端的两个迭代器,指向某个缓冲池的指针,整个缓冲区包含缓冲池的数目
但是iterate变量不同,STL中包括本缓冲池地址,本缓冲池的首尾地址,当前迭代器地址
而这个文件的iterate设计是三个,缓冲池大小,deque的地址,以及当前迭代器地址。想法是不错,但是mapindex的相关操作真的是令人费解。
既像是不变的=BUCKSIZE,但还有加减变化,但在getBuckTail那里又像是=0。又像是当前cur的索引
最后这个deque设计的着实有点差,在cpp文件中有更多说明
*/
namespace TinySTL{
template<class T, class Alloc = allocator<T> >
class deque;
namespace Detail{
//class of deque iterator
template<class T>
class dq_iter :public iterator<bidirectional_iterator_tag, T>{
//继承迭代器的内嵌类型:双向迭代器
private:
template<class T, class Alloc>
friend class ::TinySTL::deque;//互为友元
private:
//typedef TinySTL::deque<T>* cntrPtr;??为什么要加const
typedef const ::TinySTL::deque<T>* cntrPtr;
size_t mapIndex_;//==缓冲池大小
T *cur_;//本迭代器地址
cntrPtr container_;//容器deque的地址
public:
//三种初始化
dq_iter() :mapIndex_(-1), cur_(0), container_(0){
}
dq_iter(size_t index, T *ptr, cntrPtr container)
:mapIndex_(index), cur_(ptr), container_(container){
}
dq_iter(const dq_iter& it)
:mapIndex_(it.mapIndex_), cur_(it.cur_), container_(it.container_){
}
//重载运算符
dq_iter& operator = (const dq_iter& it);
reference operator *(){
return *cur_; }//dq_iter是dque的友元类
const reference operator *()const{
return *cur_; }//pointer继承自iterator
pointer operator ->(){
return &(operator*()); }
const pointer operator ->()const{
return &(operator*()); }//只能由常量指针接收
dq_iter& operator ++();
dq_iter operator ++(int);
dq_iter& operator --();
dq_iter operator --(int);
//下面几个应该为友元函数?
bool operator ==(const dq_iter& it)const;
bool operator !=(const dq_iter& it)const;
void swap(dq_iter& it);//交换迭代器
private:
T *getBuckTail(size_t mapIndex)const;
T *getBuckHead(size_t mapIndex)const;
size_t getBuckSize()const;
public:
//全局友元函数重载运算符
template<class T>//
friend dq_iter<T> operator + (const dq_iter<T>& it, typename dq_iter<T>::difference_type n);
template<class T>
friend dq_iter<T> operator + (typename dq_iter<T>::difference_type n, const dq_iter<T>& it);
template<class T>
friend dq_iter<T> operator - (const dq_iter<T>& it, typename dq_iter<T>::difference_type n);
template<class T>
friend dq_iter<T> operator - (typename dq_iter<T>::difference_type n, const dq_iter<T>& it);
template<class T>//求迭代器距离
friend typename dq_iter<T>::difference_type operator - (const dq_iter<T>& it1, const dq_iter<T>& it2);
template<class T>
friend void swap(dq_iter<T>& lhs, dq_iter<T>& rhs);
};
}// end of Detail namespace
//class of deque
template<class T, class Alloc>
class deque{
private:
template<class T>
friend class ::TinySTL::Detail::dq_iter;
public:
typedef T value_type;
typedef Detail::dq_iter<T> iterator;
typedef Detail::dq_iter<const T> const_iterator;
typedef T& reference;
typedef const reference const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef Alloc allocator_type;
private:
typedef Alloc dataAllocator;//跟上面的区别?
enum class EBucksSize{
BUCKSIZE = 64};
private:
iterator begin_, end_;//两个迭代器
size_type mapSize_;//缓冲池数量
T** map_;//迭代器数组指针
public:
//构造、复制、析构
deque();//显式初始化
explicit deque(size_type n, const value_type& val = value_type());
template <class InputIterator>
deque(InputIterator first, InputIterator last);
deque(const deque& x);
deque& operator= (const deque& x);
deque& operator= (deque&& x);
~deque();
//迭代器设计
iterator begin();
iterator end();
iterator begin()const;
iterator end()const;
public:
//迭代器相关
size_type size() const{
return end() - begin(); }
bool empty() const{
return begin() == end(); }
reference operator[] (size_type n);
reference front();
reference back();
const_reference operator[] (size_type n) const;
const_reference front() const;
const_reference back() const;
//接口函数
void push_back(const value_type& val);
void push_front(const value_type& val);
void pop_back();
void pop_front();
void swap(deque& x);
void clear();
private:
//内部实现函数
T *getANewBuck();
T** getANewMap(const size_t size);
size_t getNewMapSize(const size_t size);
size_t getBuckSize()const;
void init();
bool back_full()const;
bool front_full()const;
void deque_aux(size_t n, const value_type& val, std::true_type);
template<class Iterator>
void deque_aux(Iterator first, Iterator last, std::false_type);
void reallocateAndCopy();
public:
//全局友元函数。==、!=、<<、>>都要如此定义
template <class T, class Alloc>
friend bool operator== (const deque<T, Alloc>& lhs, const deque<T, Alloc>& rhs);
template <class T, class Alloc>
friend bool operator!= (const deque<T, Alloc>& lhs, const deque<T, Alloc>& rhs);
template <class T, class Alloc>
friend void swap(deque<T, Alloc>& x, deque<T, Alloc>& y);
};//end of deque
}
#include "Detail\Deque.cpp"
#endif
deque.cpp
#ifndef _DEQUE_IMPL_H_
#define _DEQUE_IMPL_H_
/*
这个deque,有很多细节设计的不好
*/
namespace TinySTL{
namespace Detail{
//重载迭代器运算符1
//自增
template<class T>
dq_iter<T>& dq_iter<T>::operator ++(){
if (cur_ != getBuckTail(mapIndex_))//
++cur_;
else if (mapIndex_ + 1 < container_->mapSize_){
++mapIndex_;
cur_ = getBuckHead(mapIndex_);
}
else{
//+1后跳出了map
mapIndex_ = container_->mapSize_;
//cur_ = container_->map_[mapIndex_] + getBuckSize();//指向map_[mapSize_-1]的尾的下一个位置
cur_ = container_->map_[mapIndex_];
}
return *this;
}
//后置++
template<class T>
dq_iter<T> dq_iter<T>::operator ++(int){
auto res = *this;
++(*this);
return res;
}
//前置--
template<class T>
dq_iter<T>& dq_iter<T>::operator --(){
if (cur_ != getBuckHead(mapIndex_))//当前不指向桶头
--cur_;
else if (mapIndex_ - 1 >= 0){
//-1后还在map里面
--mapIndex_;
cur_ = getBuckTail(mapIndex_);
}
else{
mapIndex_ = 0;
cur_ = container_->map_[mapIndex_];//指向map_[0]的头
}
return *this;
}
//后置--
template<class T>
dq_iter<T> dq_iter<T>::operator --(int){
auto res = *this;
--(*this);
return res;
}
template<class T>
void swap(dq_iter<T>& lhs, dq_iter<T>& rhs){
lhs.swap(rhs);
}
//重载运算符2
//+运算
template<class T>
dq_iter<T> operator + (const dq_iter<T>& it, typename dq_iter<T>::difference_type n){
//assume n >= 0
dq_iter<T> res(it);
auto m = res.getBuckTail(res.mapIndex_) - res.cur_;
if (n <= m){
//前进n步仍在同一个桶中
res.cur_ += n;
}
else{
n = n - m;
res.mapIndex_ += (n / it.getBuckSize() + 1);
auto p = res.getBuckHead(res.mapIndex_);
auto x = n % it.getBuckSize() - 1;
res.cur_ = p + x;
}
return res;
}
template<class T>
dq_iter<T> operator + (typename dq_iter<T>::difference_type n, const dq_iter<T>& it){
return (it + n);
}
//-运算
template<class T>
dq_iter<T> operator - (const dq_iter<T>& it, typename dq_iter<T>::difference_type n){
//assume n >= 0
dq_iter<T> res(it);
auto m = res.cur_ - res.getBuckHead(res.mapIndex_);
if (n <= m)//后退n步还在同一个桶中
res.cur_ -= n;
else{
n = n - m;
res.mapIndex_ -= (n / res.getBuckSize() + 1);
res.cur_ = res.getBuckTail(res.mapIndex_) - (n % res.getBuckSize() - 1);
}
return res;
}
template<class T>
dq_iter<T> operator - (typename dq_iter<T>::difference_type n, const dq_iter<T>& it){
return (it - n);
}
//求距离
template<class T>
typename dq_iter<T>::difference_type operator - (const dq_iter<T>& it1, const dq_iter<T>& it2){
if (it1.container_ == it2.container_ && it1.container_ ==0)//这个比较不奇怪吗?
return 0;
return typename dq_iter<T>::difference_type(it1.getBuckSize()) * (it1.mapIndex_ - it2.mapIndex_ - 1)
+ (it1.cur_ - it1.getBuckHead(it1.mapIndex_)) + (it2.getBuckTail(it2.mapIndex_) - it2.cur_) + 1;
}
//复制
template<class T>
dq_iter<T>& dq_iter<T>::operator = (const dq_iter& it){
if (this != &it){
mapIndex_ = it.mapIndex_;
cur_ = it.cur_;
container_ = it.container_;
}
return *this;
}
//缓冲池相关操作
template<class T>
T *dq_iter<T>::getBuckTail(size_t mapIndex)const{
return container_->map_[mapIndex] + (container_->getBuckSize() - 1);//container_->map_[mapIndex]-1);这样不好吗?
}
template<class T>
T *dq_iter<T>::getBuckHead(size_t mapIndex)const{
return container_->map_[mapIndex];
}
template<class T>
size_t dq_iter<T>::getBuckSize()const{
//缓冲池数组大小
return container_->getBuckSize();
}
}//end of Detail namespace
//迭代器相关函数
template<class T, class Alloc>
typename deque<T, Alloc>::reference deque<T, Alloc>::operator[] (size_type n){
return *(begin() + n);
}
template<class T, class Alloc>
typename deque<T, Alloc>::reference deque<T, Alloc>::front(){
return *begin();
}
template<class T, class Alloc>
typename deque<T, Alloc>::reference deque<T, Alloc>::back(){
return *(end() - 1);
}
//由于const迭代器的设计失误故以下三个const函数会丧失const特性
template<class T, class Alloc>
typename deque<T, Alloc>::const_reference deque<T, Alloc>::operator[] (size_type n) const{
return *(begin() + n);
}
template<class T, class Alloc>
typename deque<T, Alloc>::const_reference deque<T, Alloc>::front() const{
return *begin();
}
template<class T, class Alloc>
typename deque<T, Alloc>::const_reference deque<T, Alloc>::back() const{
return *(end() - 1);
}
template<class T, class Alloc>
typename deque<T, Alloc>::iterator deque<T, Alloc>::begin(){
return begin_; }
template<class T, class Alloc>
typename deque<T, Alloc>::iterator deque<T, Alloc>::end(){
return end_; }
//迭代器设计失误,会使下面两个函数丧失const特性,暂时没有效解决办法故只能先这样妥协
template<class T, class Alloc>
typename deque<T, Alloc>::iterator deque<T, Alloc>::begin()const{
return begin_; }
template<class T, class Alloc>
typename deque<T, Alloc>::iterator deque<T, Alloc>::end()const{
return end_; }
//析构函数
template<class T, class Alloc>
deque<T, Alloc>::~deque(){
for (int i = 0; i != mapSize_; ++i){
for (auto p = map_[i] + 0; !p && p != map_[i] + getBuckSize(); ++p)
dataAllocator::destroy(p);
if (!map_[i])
dataAllocator::deallocate(map_[i], getBuckSize());
}
delete[] map_;
}
//构造函数,这个deque构造函数就写的不好
/*无参构造,没有,只给了两个默认参数,那么问题来了,他的初始化在什么地方呢?只能在插入第一个元素的时候,那么问题来了
初始化首先要经过empty(),但是没有给begin_和end_赋初值,所以要怎么调用empty比呢?*/
template<class T, class Alloc>
deque<T, Alloc>::deque()
:mapSize_(0), map_(0){
}
template<class T, class Alloc>
deque<T, Alloc>::deque(size_type n, const value_type& val = value_type()){
deque();
deque_aux(n, val, typename std::is_integral<size_type>::type());
}
template<class T, class Alloc>
template <class InputIterator>
deque<T, Alloc>::deque(InputIterator first, InputIterator last){
deque();
deque_aux(first, last, typename std::is_integral<InputIterator>::type());
}
/*上面三个初始化的问题都在少赋初值,而下面这个问题就大多了,首先连初始化都没有,就直接开始了?直接就到了getAnewMap去了?
而且在这个过程中,并没有对deque成员变量的初始化。实际上这个初始化,明显可以调用
deque_aux(x.begin(), x.end(), typename std::is_integral<InputIterator>::type())*/
template<class T, class Alloc>
deque<T, Alloc>::deque(const deque& x){
mapSize_ = x.mapSize_;
map_ = getANewMap(mapSize_);
for (int i = 0; i + x.begin_.mapIndex_ != x.mapSize_; ++i)
for (int j = 0; j != getBuckSize(); ++j)
map_[x.begin_.mapIndex_ + i][j] = x.map_[x.begin_.mapIndex_ + i][j];
begin_.mapIndex_ = x.begin_.mapIndex_;
end_.mapIndex_ = x.end_.mapIndex_;
begin_.cur_ = map_[begin_.mapIndex_] + (x.begin_.cur_ - x.map_[x.begin_.mapIndex_]);
end_.cur_ = map_[end_.mapIndex_] + (x.end_.cur_ - x.map_[x.end_.mapIndex_]);
begin_.container_ = end_.container_ = this;
}
//接口函数
//后插
template<class T, class Alloc>
void deque<T, Alloc>::push_back(const value_type& val){
if (empty()){
init();
}
else if (back_full()){
reallocateAndCopy();
}
//*end_ = val;
//bug fix
//2015.01.02
TinySTL::construct(end_.cur_, val);//赋值
++end_;//初始化的过程中end_根本就没有调用过,怎么自加?
}
//前插
template<class T, class Alloc>
void deque<T, Alloc>::push_front(const value_type& val){
if (empty()){
init();
}
else if (front_full()){
reallocateAndCopy();
}
--begin_;
//*begin_ = val;
//bug fix
//2015.01.02
TinySTL::construct(begin_.cur_, val);
}
//前删
template<class T, class Alloc>
void deque<T, Alloc>::pop_front(){
dataAllocator::destroy(begin_.cur_);
++begin_;
}
//后删
template<class T, class Alloc>
void deque<T, Alloc>::pop_back(){
--end_;
dataAllocator::destroy(end_.cur_);
}
//清空
template<class T, class Alloc>
void deque<T, Alloc>::clear(){
/*for (int i = 0; i != mapSize_; ++i)
if (!map_[i])
dataAllocator::destroy(map_[i], map_[i] + getBuckSize());*/
for (auto i = 0; i != mapSize_; ++i){
for (auto p = map_[i] + 0; !p && p != map_[i] + getBuckSize(); ++p)
dataAllocator::destroy(p);
}
mapSize_ = 0;
begin_.mapIndex_ = end_.mapIndex_ = mapSize_ / 2;
begin_.cur_ = end_.cur_ = map_[mapSize_ / 2];
}
template<class T, class Alloc>
void deque<T, Alloc>::swap(deque<T, Alloc>& x){
TinySTL::swap(mapSize_, x.mapSize_);
TinySTL::swap(map_, x.map_);
begin_.swap(x.begin_);
end_.swap(x.end_);
}
//**********************内部辅助函数***************************
//重新申请内存转移
template<class T, class Alloc>
void deque<T, Alloc>::reallocateAndCopy(){
auto newMapSize = getNewMapSize(mapSize_);
T** newMap = getANewMap(newMapSize);
size_t startIndex = newMapSize / 4;
for (int i = 0; i + begin_.mapIndex_ != mapSize_; ++i)
for (int j = 0; j != getBuckSize(); ++j)
newMap[startIndex + i][j] = map_[begin_.mapIndex_ + i][j];
size_t n = begin_.cur_ - map_[begin_.mapIndex_];
auto size = this->size();
auto b = begin_, e = end_;
clear();
mapSize_ = newMapSize;
map_ = newMap;
begin_ = iterator(startIndex, newMap[startIndex] + n, this);
end_ = begin_ + size;
}
//看后边是不是满了
template<class T, class Alloc>
bool deque<T, Alloc>::back_full()const{
return map_[mapSize_ - 1] && (map_[mapSize_]) == end().cur_;
}
//看前边是不是满了
template<class T, class Alloc>
bool deque<T, Alloc>::front_full()const{
return map_[0] && map_[0] == begin().cur_;
}
//辅助插入。这个函数也存在很大的问题,因为是转化为前插和后插,所以如果都等到插入完了,才发现不够岂不是浪费空间和时间?
template<class T, class Alloc>
void deque<T, Alloc>::deque_aux(size_t n, const value_type& val, std::true_type){
int i = 0;
for (; i != n / 2; ++i)
(*this).push_front(val);
for (; i != n; ++i)
(*this).push_back(val);
}
template<class T, class Alloc>
template<class Iterator>
void deque<T, Alloc>::deque_aux(Iterator first, Iterator last, std::false_type){
difference_type mid = (last - first) / 2;
for (auto it = first + mid; it != first - 1; --it)
(*this).push_front(*it);
for (auto it = first + mid + 1; it != last; ++it)
(*this).push_back(*it);
}
//初始化
template<class T, class Alloc>
void deque<T, Alloc>::init(){
mapSize_ = 2;//这个初始化为2,STL中为》=8
map_ = getANewMap(mapSize_);//获取一个缓冲池
begin_.container_ = end_.container_ = this;
begin_.mapIndex_ = end_.mapIndex_ = mapSize_ - 1;//这个mapIndex设计的着实有点让人看不懂
begin_.cur_ = end_.cur_ = map_[mapSize_ - 1];
}
//获取一个新的缓冲池
template<class T, class Alloc>
T *deque<T, Alloc>::getANewBuck(){
return dataAllocator::allocate(getBuckSize());
}
//获取新的缓冲区
template<class T, class Alloc>
T** deque<T, Alloc>::getANewMap(const size_t size){
T **map = new T*[size];
for (int i = 0; i != size; ++i)
map[i] = getANewBuck();
return map;
}
//似乎没必要单独写一个函数,但写出来的好处是,不用修改重新申请内存的函数
template<class T, class Alloc>
size_t deque<T, Alloc>::getNewMapSize(const size_t size){
return (size == 0 ? 2 : size * 2);
}
//缓冲池大小
template<class T, class Alloc>
size_t deque<T, Alloc>::getBuckSize()const{
return (size_t)EBucksSize::BUCKSIZE;
}
//友元运算符和swap
template <class T, class Alloc>
bool operator== (const deque<T, Alloc>& lhs, const deque<T, Alloc>& rhs){
auto cit1 = lhs.begin(), cit2 = rhs.begin();
for (; cit1 != lhs.end() && cit2 != rhs.end(); ++cit1, ++cit2){
if (*cit1 != *cit2)
return false;
}
if (cit1 == lhs.end() && cit2 == rhs.end())
return true;
return false;
}
template <class T, class Alloc>
bool operator!= (const deque<T, Alloc>& lhs, const deque<T, Alloc>& rhs){
return !(lhs == rhs);
}
template <class T, class Alloc>
void swap(deque<T, Alloc>& x, deque<T, Alloc>& y){
x.swap(y);
}
}
#endif