【C++】用模板实现顺序表

来源:互联网 发布:好用的防晒霜推荐知乎 编辑:程序博客网 时间:2024/05/16 08:44

使用模板写出来的类或函数,与类型无关,下面用模板实现顺序表

template <typename T>class Vector{public:typedef T* Iterator;Vector()//构造函数: _start(0), _finish(0), _endofstorage(0){}Vector(const T* arr, size_t size): _start(new T[size]), _finish(_start + size)//_finish(_start), _endofstorage(_start + size){for (size_t i = 0; i < size; i++)_start[i] = arr[i];//*_finish++ = arr[i];}Vector(const Vector<T>& v)//拷贝构造{size_t size = v.Size();_start = new T[size];for (size_t i = 0; i < size; i++)_start[i] = v._start[i];_finish = _start + size;_endofstorage = _finish;}Vector& operator=(const Vector<T>& v)//赋值{size_t size = v.Size();if (this != &v){T* tmp = new T[size];for (size_t i = 0; i < size; i++)tmp[i] = v._start[i];delete[] _start;_start = tmp;_finish = _start + size;_endofstorage = _finish;}return *this;}~Vector()//析构{if (_start){delete[] _start;_start = NULL;}}//////////////////////Iterator////////////////////////////Iterator Begin()    //迭代器{return _start;}Iterator End(){return _finish;}//////////////////////Modify//////////////////////////////void PushBack(const T& data)   //尾插{_CheckCapacity();*_finish = data;_finish++;}void PopBack()//尾删{assert(_start < _finish);_finish--;}void Insert(size_t pos, const T& data)//任意位置插入{assert(pos <= Size());_CheckCapacity();for (size_t i = Size(); i > pos; i--)_start[i] = _start[i - 1];_start[pos] = data;_finish++;}void Erase(size_t pos)//任意位置删除{assert(pos <= Size());for (size_t i = pos; i < Size(); i++)_start[i] = _start[i + 1];_finish--;}/////////////////////Capacity///////////////////////////size_t Size()const//大小{return _finish - _start;}size_t Capacity()const//容量{return _endofstorage - _start;}bool Empty()const//叛空{if (_finish == _start)return true;return false;}void Resize(size_t newSize, const T& data = T())//改变大小{size_t oldsize = Size();size_t capacity = Capacity();if (newSize <= oldsize)_finish = _start + newSize;else if (newSize > oldsize && newSize <= capacity){for (size_t i = oldsize; i < newSize;i++)*_finish++ = data;}else{T* tmp = new T[newSize];for (size_t i = 0; i < oldsize; i++)tmp[i] = _start[i];for (size_t i = oldsize; i < newSize; i++)tmp[i] = data;delete[] _start;_start = tmp;_finish = _start + newSize;_endofstorage = _start + newSize;}}////////////////////Element Access//////////////////////T& operator[](size_t index){assert(index <= Capacity());return _start[index];}const T& operator[](size_t index)const{assert(index <= Capacity());return _start[index];}T& Front()//头元素{return *_start;}const T& Front()const{return *_start;}T& Back()//尾元素{return *(_finish-1);}const T& Back()const{return *(_finish-1);}void Clear(){_finish = _start;}template<class T>friend ostream& operator<<(ostream& _cout, const Vector<T>& v)//输出运算符重载{for (size_t i = 0; i < v.Size(); i++)_cout << v._start[i] <<" ";return _cout;}private:void _CheckCapacity(){size_t size = Size();size_t capacity = Capacity();size_t newCapacity = 2 * capacity + 3;if (size >= capacity){T* tmp = new T[newCapacity];for (size_t i = 0; i < size; i++)tmp[i] = _start[i];delete[] _start;_start = tmp;_finish = _start + size;_endofstorage = _start + newCapacity;}}private:T* _start;T* _finish;T* _endofstorage;};
memcpy实际上是浅拷贝,因此对于涉及到空间创建释放时,需要用for循环,for循环中的赋值运算符经过自己的重载,不会再出现浅拷贝的问题了。

如果使用迭代器实现任意位置的插入与删除,我们可以将代码改为如下:

void Insert(Iterator pos, const T& data){_CheckCapacity();Iterator i = End();for (; i != pos; i--)*i = *(i - 1);*pos = data;_finish++;}void Erase(Iterator pos){Iterator end = End();for (Iterator i = pos; i != --end; i++)*(i) = *(i + 1);_finish--;}
迭代器实际上就是个指针,在使用任意位置插入的时候,如果finish==endofstorage时,我们会扩容,即(开辟更大的新空间,复制元素,释放旧空间),此时新空间已经不是旧空间了,原先的旧空间由于被释放了,End()已经找不到了。而我们前面写的插入,由于传参为插入位置的下标,不存在这样的问题。
 
原创粉丝点击