STL的vector容器是一种动态数组,它实现了在尾部插入或删除元素时,时间复杂度为O(1),而在头部或中部插入或删除元素时,时间复杂度为线性阶O(n)。相比静态数组,vector可以动态扩展内存空间,而不需要像数组那样预先分配固定的内存空间。
vector容器的迭代器是支持随机访问的迭代器,这使得vector在访问元素时具有很高的效率。vector容器提供了许多操作函数,例如push_back()用于在尾部添加元素,erase()用于删除元素,insert()用于在指定位置插入元素等。
在C++中,vector容器的定义方式为:std::vector<T> v;其中,std是命名空间,vector是类名,T是存储元素的类型,v是对象名。可以通过使用push_back()函数或者使用下标运算符[]来向vector中添加或访问元素。
vector容器是一种非常实用的动态数组,它具有高效的插入、删除和访问功能,并且可以动态扩展内存空间。
构造函数和析构函数
vector()//构造函数
:_start(nullptr)
,_finish(nullptr)
,_endofstorage(nullptr)
{}
~vector()//析构函数
{
delete[] _start;
_start = _finish = _endofstorage = nullptr;
}
获取第一个和最后一个数据
iterator begin()//第一个位置(迭代器)
{
return _start;
}
iterator end()//最后一个位置的下一位
{
return _finish;
}
const_iterator begin() const
{
return _start;
}
const_iterator end() const
{
return _finish;
}
扩容函数和下标访问
void reserve(size_t n)//扩容函数
{
if (n > capacity())
{
size_t sz = size();
T* tmp = new T[n];
if (_start)
{
//memcpy会有增容问题(按字节拷贝造成浅拷贝
//memcpy(tmp, _start, sizeof(T) * sz);
for(size_t i=0;i<sz;i++)
{
tmp[i] = _start[i];//调用operator=,是深拷贝
}
delete[] _start;
}
_start = tmp;
_finish = tmp + sz;
_endofstorage = tmp + n;
}
}
T& operator[](size_t i)//下标访问
{
assert(i < size());
return _start[i];
}
const T& operator[](size_t i) const//const下标访问
{
assert(i < size());
return _start[i];
}
删除数据和拷贝构造
void pop_back()//删除数据
{
/*assert(_start > _finish);//不能把_start前面的数据删了
--_finish;*/
erase(_finish - 1);//复用
}
//vector(const vector<T>& v)//实现拷贝构造v2(v),不写会造成浅拷贝问题
//{
// _start = new T[v.capacity()];//v2要开空间
// _finish = _start;
// _endofstorage = _start + v.capacity();
// for (size_t i = 0; i < v.size(); i++)//把v的数据给v2
// {
// *_finish = v[i];
// ++_finish;
// }
//}
vector(const vector<T>& v)//v2(v),效果同上,先把v2初始化为空
:_start(nullptr)
,_finish(nullptr)
,_endofstorage(nullptr)
{
reserve(v.capacity());//把v2扩容一下
for (const auto& e : v)//遍历v,把v的数据插入到v2
{
push_back(e);
}
}
iterator erase(iterator pos)//删除pos位置的值
{
assert(pos < _finish);//pos要指向有效位置
iterator it = pos;
while (it < _finish)//从后往前挪动覆盖
{
*it = *(it + 1);
++it;
}
--_finish;
return pos;//返回pos位置的下一个数据,但把pos删了,pos位置的下一个数据就是pos
}
改变容量函数和operator运算符重载
void resize(size_t n, const T& val = T())
{
if (n < size())
{
_finish = _start + n;
}
else
{
if (n > capacity())
{
reserve(n);
}
while (_finish < _start + n)//扩容的数据都填上val
{
*_finish = val;
++_finish;
}
}
}
vector<T>& operator=(vector<T> v)//v1=v3简单写法
{
swap(v);
return *this;
}
迭代器和插入数据
void insert(iterator pos, const T& x)//在pos位置插入数据
{
assert(pos <= _finish);// =是尾插
if (_finish == _endofstorage)//扩容
{
size_t n = pos - _start;//计算扩容前pos位置之前的数据长度
size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2;
reserve(newcapacity);
pos = _start + n;//若增容原来的pos会失效,需要重新计算位置
}
iterator end = _finish - 1;
while (end >= pos)//挪动数组的数据,pos也要挪动
{
*(end + 1) = *end;
--end;
}
*pos = x;
++_finish;
}
void print_vector(const vector<int>& v)//只读迭代器
{
vector<int>::const_iterator it = v.begin();
while (it != v.end())
{
//*it += 1;
cout << *it << " ";
it++;
}
cout << endl;
}
void push_back(const T& x)//尾插数据
{
//if (_finish == _endofstorage)//满了就扩容
//{
// size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2;
// reserve(newcapacity);
//}
//*_finish = x;
//++_finish;
insert(_finish,x);
}
有效数据和容量
size_t size() const//有效数据个数
{
return _finish - _start;
}
size_t capacity() const//总容量
{
return _endofstorage - _start;
}
代码整合+测试
namespace LXQ1
{
template<class T>
class vector
{
public:
typedef T* iterator;
typedef const T* const_iterator;
//把以上代码拷贝过来
void swap(vector<T>& v)//为何要自己写swap?因为库函数使用深拷贝代价大
{
::swap(_start, v._start);//交换指针,调用全局的swap
::swap(_finish, v._finish);
::swap(_endofstorage, v._endofstorage);
}
private:
iterator _start;//指向第一个位置
iterator _finish;//指向最后位置的下一位
iterator _endofstorage;// 等于_start+capacity
};
void print_vector(const vector<int>& v)
{
vector<int>::const_iterator it = v.begin();//返回的是第一个位置的指针
while (it != v.end())//end是最后一个位置的下一个位置
{
cout << *it << " ";
++it;
}
cout << endl;
}
void test1()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(6);
v.push_back(7);
print_vector(v);
cout << v.size() << endl;
cout << v.capacity() << endl;
vector<int>::iterator it = v.begin();
while (it!=v.end())
{
*it += 1;
cout << *it << " ";
it++;
}
cout << endl;
for (auto& e : v)//底层是迭代器
{
e -= 1;//auto e没有改变指针,只是改变了e,需要auto& e
cout << e<< " ";
}
cout << endl;
for (size_t i = 0; i < v.size(); i++)
{
cout << v[i]<< " ";
}
cout << endl;
}
void test2()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.insert(v.begin(), 0);//头插
for (size_t i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
vector<int>::iterator it = v.begin();//删除偶数(迭代器失效问题)
while (it != v.end())
{
if (*it % 2 == 0)
{
it = v.erase(it);//一定要获取返回值,否则迭代器失效
}
else
{
it++;
}
}
for (size_t i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
}
void test3()
{
vector<int> v;
v.reserve(10);
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(6);
v.push_back(7);
print_vector(v);
cout << v.size() << endl;
cout << v.capacity() << endl << endl;
v.resize(4);
print_vector(v);
cout << v.size() << endl;
cout << v.capacity() << endl << endl;
v.resize(8);//默认给缺省值
print_vector(v);
cout << v.size() << endl;
cout << v.capacity() << endl << endl;
v.resize(12,12);//填上12
print_vector(v);
cout << v.size() << endl;
cout << v.capacity() << endl << endl;
}
void test4()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
for (size_t i = 0; i < v1.size(); i++)
{
cout << v1[i] << " ";
}
cout << endl;
vector<int> v2(v1);//拷贝构造
for (size_t i = 0; i < v2.size(); i++)
{
cout << v2[i] << " ";
}
cout << endl;
vector<int> v3;
v3.push_back(10);
v3.push_back(20);
v3.push_back(30);
v3.push_back(40);
v3.push_back(50);
v1 = v3;
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}
void test5()
{
vector<string> v;
v.push_back("111333333333333333333333");
v.push_back("22266666666666666666666666");
v.push_back("2226666666000666666666669999999 ");
//程序会崩溃,当T是string时的增容问题,本质是memcpy造成的浅拷贝问题
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
}
}