一、vector
vector是一种数据结构,一种顺序容器
其中的元素是严格按照线性顺序排列储存的,通常实现为动态数组,操作和常规的数组类型类似
不同的是,vector里的存储空间分配自动完成,可以根据需要动态扩大和缩小
二、模拟实现
1.实现步骤思路
1.1创建vector类框架
类属性 :类似指针三个
指向数据开始
iterator _start=nullptr;
指向数据的尾iterator _finish= nullptr;
指向存储容量的尾iterator _endOfStorage= nullptr;
类方法
构造函数
拷贝构造
重载赋值
析构函数
随机插入、删除
扩容
类数组下标访问
1.2具体类方法实现
构造函数
无参初始化可以采取在类属性位置设置缺省参数
有参初始化代码示例如下:
vector(int n, const T& value = T())
//这里初始化为0,只能使用匿名对象调用默认构造
//这里的T不一定是整型,最好也初始化
{
reserve(n);
for (int i = 0; i < n; i++) {
push_back(value);
}
}
拷贝构造
代码示例如下:
vector(const vector<T>& v)
{
//根据待拷贝的容量new一个新数组
_start = new T[v.capacity()];
for (size_t i = 0; i < v.size(); i++)
{
_start[i] = v._start[i];
}
_finish = _start + v.size();
_endOfStorage = _start + v.capacity();
}
重载赋值
赋值和拷贝构造区别在于赋值的这个变量已存在
代码示例如下:
vector<T>& operator= (vector<T> v)
{
_start = new T[v.capacity()];
for (size_t i = 0; i < v.size(); i++)
{
_start[i] = v._start[i];
}
_finish = _start + v.size();
_endOfStorage = _start + v.capacity();
return *this;
}
_类数组下标访问重载
代码示例如下:
const T& operator[](size_t pos)const
{
assert(pos < size());
return _start[pos];
}
析构函数
代码示例如下:
~vector() {
delete[] _start;
_start = _finish = _endOfStorage = nullptr;
}
随机尾插尾删
代码示例如下:
iterator insert(iterator pos, const T& val) {
assert(pos >= _start);
assert(pos <= _finish);
if (_finish == _endOfStorage)
{
size_t len = pos - _start;
reserve(capacity() == 0 ? 4 : capacity() * 2);
// 扩容后更新pos,解决pos失效的问题
pos = _start + len;
}
iterator end = _finish - 1;
//将数据往后挪
while (end >= pos)
{
*(end + 1) = *end;
--end;
}
*pos = val;
++_finish;
return pos;
}
iterator erase(iterator pos)
{
assert(pos >= _start);
assert(pos < _finish);
iterator start = pos + 1;
while (start != _finish)
{
*(start - 1) = *start;
++start;
}
--_finish;
return pos;
}
扩容
代码示例如下:
void reserve(size_t n)//扩容
{
if (n > capacity())
{
size_t sz = size();//需要保存原有的数据个数
T* tmp = new T[n];
if (_start)//若原来里面存在数据
{
//memcpy(tmp, _start, sizeof(T) * size()); 会在后面造成二次浅拷贝
for (size_t i = 0; i < sz; ++i)
{
tmp[i] = _start[i];
}
delete[] _start;
}
_start = tmp;
_finish = _start + sz;
_endOfStorage = _start + n;
}
}
三、迭代器模拟实现以及失效
1.实现步骤思路
vetor这种顺序容器实现起来很简单
只需模仿类似指针操作
正向迭代器
代码示例如下:
typedef T* iterator;
typedef const T* const_iterator;
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const_iterator begin() const
{
return _start;
}
const_iterator end() const
{
return _finish;
}
反向向迭代器
先创建个反向迭代器通类
代码示例如下:
namespace tc {
template<class Iterator, class Ref, class Ptr>
struct ReverseIteraor
{
typedef ReverseIteraor<Iterator, Ref, Ptr> self;
Iterator _cur;
ReverseIteraor(Iterator it)
:_cur(it)
{}
Ref operator*()
{
Iterator tmp = _cur;
--tmp;
return *tmp;
}
self& operator++()
{
--_cur;
return *this;
}
self& operator--()
{
++_cur;
return *this;
}
bool operator!=(const self& s)
{
return _cur != s._cur;
}
bool operator==(const self& s)
{
return _cur == s._cur;
}
};
}
后将正向迭代器传入反向迭代器参数中即可
代码示例如下:
typedef ReverseIteraor<iterator, T&, T*> reverse_iterator;
typedef ReverseIteraor<iterator, const T&,const T*> const_reverse_iterator;
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
reverse_iterator rend()
{
return reverse_iterator (begin());
}
2.迭代器失效
随机插入、删除都可能会导致迭代器失效
原因:
插入可能会导致容量发生变化导致扩容,还有整体数据的后移都会改变迭代器指向的位置发生变化
删除也会导致删除位置后的数据整体移位进而修改迭代器指向的位置失效出现访问错误。
解决办法:
插入删除的时候返回删除位置下一个数据的位置
当前位置会失效
析构函数崩溃
原因:
扩容、拷贝构造都可能会造成析构函数的崩溃,简单使用memcpy拷贝
解决办法:
所以必须在扩容,拷贝构造时就采取深拷贝,此处千万不能使用memcpy浅拷贝
四、模拟测试
测试代码:
void test_vector1()
{
cout<<"测试push_back" << endl;
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
func(v1);
for (size_t i = 0; i < v1.size(); ++i)
{
cout << v1[i] << " ";
}
cout << endl;
v1.pop_back();
v1.pop_back();
vector<int>::iterator it = v1.begin();
while (it != v1.end())
{
cout << *it << " ";
++it;
}
cout << endl;
v1.pop_back();
v1.pop_back();
v1.pop_back();
//v1.pop_back();
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
//func(v1);
}
//template<class T>
//void f()
//{
// T x = T();
// cout << x << endl;
//}
//void test_vector2()
//{
// // 内置类型有没有构造函数
///* int i = int();
// int j = int(1);*/
// f<int>();
// f<int*>();
// f<double>();
//}
void test_vector2()
{
cout << "测试resize" << endl;
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
cout << v1.size() << endl;
cout << v1.capacity() << endl;
v1.resize(10);
cout << v1.size() << endl;
cout << v1.capacity() << endl;
//func(v1);
v1.resize(3);
//func(v1);
cout << endl;
}
void test_vector3()
{
cout << "测试插入,迭代器失效" << endl;
std::vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
//v1.push_back(5);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
/*v1.insert(v1.begin(), 0);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;*/
auto pos = find(v1.begin(), v1.end(), 3);
if (pos != v1.end())
{
//v1.insert(pos, 30);
pos = v1.insert(pos, 30);
}
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
// insert以后我们认为pos失效了,不能再使用
(*pos)++;
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}
void test_vector4()
{
cout << "测试删除" << endl;
std::vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
//auto pos = find(v1.begin(), v1.end(), 2);
auto pos = find(v1.begin(), v1.end(), 4);
if (pos != v1.end())
{
v1.erase(pos);
}
//(*pos)++;
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}
void test_vector5()
{
cout <<"不同的删除" << endl;
tc::vector<int> v1;
v1.push_back(10);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
v1.push_back(50);
tc::vector<int>::iterator it = v1.begin();
while (it != v1.end())
{
if (*it % 2 == 0)
{
it = v1.erase(it);
}
else
{
++it;
}
}
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}
void test_vector6()
{
cout << "测试成员函数中含有自定义类型拷贝容易出现浅拷贝问题" << endl;
vector<int> v1(10, 5);
//vector<int> v1(10, 5);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
//这里的begin使用传值返回,所以不能使用v1.begin()++
vector<int> v2(v1.begin() + 1, v1.end() - 1);
for (auto e : v2)
{
cout << e << " ";
}
cout << endl;
std::string s1("hello");
vector<int> v3(s1.begin(), s1.end());
for (auto e : v3)
{
cout << e << " ";
}
cout << endl;
int a[] = { 100, 10, 2, 20, 30 };
vector<int> v4(a, a + 3);
for (auto e : v4)
{
cout << e << " ";
}
cout << endl;
v1.insert(v1.begin(), 10);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
sort(v1.begin(), v1.end());
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
for (auto e : a)
{
cout << e << " ";
}
cout << endl;
//sort(a, a+sizeof(a)/sizeof(int));
/* greater<int> g;
sort(a, a + sizeof(a) / sizeof(int), g);*/
sort(a, a + sizeof(a) / sizeof(int));
//sort(a, a + sizeof(a) / sizeof(int), greater<int>());
for (auto e : a)
{
cout << e << " ";
}
cout << endl;
cout << endl;
}
class Solution {
public:
vector<vector<int>> generate(int numRows) {
vector<vector<int>> vv;
vv.resize(numRows, vector<int>());
for (size_t i = 0; i < vv.size(); ++i)
{
vv[i].resize(i + 1, 0);
vv[i][0] = vv[i][vv[i].size() - 1] = 1;
}
for (size_t i = 0; i < vv.size(); ++i)
{
for (size_t j = 0; j < vv[i].size(); ++j)
{
if (vv[i][j] == 0)
{
vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];
}
}
}
return vv;
}
};
void test_vector7()
{
cout << "测试拷贝构造" << endl;
vector<int> v1(10, 5);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
vector<int> v2(v1);
for (auto e : v2)
{
cout << e << " ";
}
cout << endl;
vector<std::string> v3(3, "111111111111111111111");
for (auto e : v3)
{
cout << e << " ";
}
cout << endl;
vector<std::string> v4(v3);
for (auto e : v4)
{
cout << e << " ";
}
cout << endl;
cout << endl;
v4.push_back("2222222222222222222");
v4.push_back("2222222222222222222");
v4.push_back("2222222222222222222");
for (auto e : v4)
{
cout << e << " ";
}
cout << endl;
vector<vector<int>> ret = Solution().generate(5);
for (size_t i = 0; i < ret.size(); ++i)
{
for (size_t j = 0; j < ret[i].size(); ++j)
{
cout << ret[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
void test_vector8()
{
cout << "测试vect正反向迭代器输出" << endl;
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(32);
v1.push_back(4);
v1.push_back(5);
tc::vector<int>::iterator it = v1.begin();
while (it != v1.end())
{
cout << *it << " ";
++it;
}
cout << endl;
tc::vector<int>::reverse_iterator rit = v1.rbegin();
while (rit != v1.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
}
}