目录
1. 基本成员函数
2. 默认成员函数
2.1 构造函数
2.2 析构函数
2.3 拷贝构造函数
2.4 赋值运算符重载函数
3. 容器访问相关函数
3.1 operator[ ]运算符重载
3.2 迭代器
3.3 范围for
4. vector空间增长问题
4.1 vector 容量和大小
4.2 vector扩容
4.3 重新定义大小
5. vector插入和删除
5.1 尾插
5.2 插入insert
5.3 尾删
5.4 erase删除
5.5 clear清空数据
6.总代码
6.1 vector.h
6.2 test.cpp
1. 基本成员函数
基本成员函数为三个指针,分别指向vector的开始,有效数字的位置,和容器的容量。
namespace cpp { template<class T> class vector { public: typedef T* iterator; typedef const T* const_iterator; private: iterator _start; //指向容器的头 iterator _finish; //指向有效数据的尾 iterator _endofstoage;//指向容器的尾 }; }
2. 默认成员函数
2.1 构造函数
- (1)无参构造 vector<T> v
只需要把每个成员变量初始化为nullptr即可。
//无参构造函数 vector() :_start(nullptr) , _finish(nullptr) , _endofstoage(nullptr) {}
- (2)有参构造 vector(v.begin(),v.end())
有残构造是将区间[first,last]中的数据拷贝给本身。
vector的带参构造函数首先在初始化列表对基本成员变量初始化,在将迭代器区间在[first, last)的数据一个个尾插到容器当中即可:
//带参构造函数 template <class InputIterator>//函数模板 vector(InputIterator first, InputIterator last) : _start(nullptr) , _finish(nullptr) , _endofstoage(nullptr) { //将迭代器区间在[first, last)的数据一个个尾插到容器当中 while (first != last) { push_back(*first); first++; } }
- (3)用n个val去初始化vector vector(n,val)
vector的构造函数还支持用n个val去初始化,只需要先调用reserve函数开辟n个大小的空间,再利用for循环把val的值依次push_back尾插进去即可。
//用n个val来构造vector vector(size_t n, const T& val = T()) : _start(nullptr) , _finish(nullptr) , _endofstoage(nullptr) { reserve(n); for (size_t i = 0; i < n; i++) { push_back(val); } }
这样写会出现一个问题:内存寻址错误。当我想实现下面的语句时:
cpp::vector<int> v(10, 4);
这里我调用的地方两个参数都是int,此时调用构造函数时匹配的是第二个传迭代器区间的构造函数,导致这样的原因在于编译器会优先寻找最匹配的那个函数。此构造函数的第一个参数是unsigned int类型,所以不会优先匹配此构造函数。因此我们需要再重载一个第一个参数为int类型的构造函数即可解决:
vector(int n, const T& val = T()) : _start(nullptr) , _finish(nullptr) , _endofstoage(nullptr) { reserve(n); for (int i = 0; i < n; i++) { push_back(val); } }
2.2 析构函数
首先判断该容器_start是否为空,不为空就释放空间+置空即可。
//析构函数 ~vector() { if (_start)//避免释放空指针 { delete[] _start;//释放容器所指向的空间 _start = _finish = _endofstoage = nullptr;//置空 } }
2.3 拷贝构造函数
- vector(const vector &vec)
拷贝构造可以借助先前string的拷贝构造思路,利用现代方法解决,首先对基本成员变量进行初始化,接着建立一个tmp的模板将要拷贝的数据利用构造函数去传递过去,再将这个tmp模板与自己交换即可。
//拷贝构造函数 vector(const vector<T>& v) :_start(nullptr) , _finish(nullptr) , _endofstoage(nullptr) { vector<T> tmp(v.begin(), v.end());//调用构造函数 swap(tmp); }
2.4 赋值运算符重载函数
这里是传值传参,没有引用传参,直接利用vector调用构造函数返回的值与左值进行swap交换即可进行赋值。
//赋值运算符重载 vector<T>& operator=(vector<T> v)//调用构造 { this->swap(v);//交换这两个对象 return *this;//返回 }
3. 容器访问相关函数
3.1 operator[ ]运算符重载
直接返回pos位置的数据即可进行下标+[ ]的方式进行访问。
//operator[]运算符重载 T& operator[](size_t pos) { assert(pos < size());//检测pos的合法性 return _start[pos]; }
为了方便const对象也可以调用[ ]运算符重载,因此还推出了一个const版本的[ ]运算符重载。
//const版本的[]运算符重载 const T& operator[](size_t pos) const { assert(pos < size());//检测pos的合法性 return _start[pos]; }
3.2 迭代器
vector的begin直接返回容器的_start起始位置即可,vector的end返回容器的_finish的位置。
//begin iterator begin() { return _start;//返回容器起始位置 } //end iterator end() { return _finish;//返回有效数据下一个的地址 }
const版本的迭代器如下:
//const版本迭代器 const_iterator begin() const { return _start; } //end const_iterator end() const { return _finish; }
3.3 范围for
范围for的底层是通过迭代器实现:
void test_vector() { cpp::vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); v.push_back(5); //范围for for (auto e : v) { cout << e << " ";//1 2 3 4 5 } }
4. vector空间增长问题
4.1 vector 容量和大小
指针相减可以得到对应的个数,因此获取size只需_finish - _start。获取capacity只需_endofstoage - _start。
- (1)size
size_t size() const //最好加上const,普通对象和const对象均可调用 { return _finish - _start; //指针相减就能得到size的个数 }
- (2)capacity
size_t capacity() const { return _endofstoage - _start; }
4.2 vector扩容
- reserve(int len);
reserve扩容和string的扩容非常相似。先开辟一块新的扩好容的空间,如果旧空间里头有数据,那么就利用for循环将容器中的数据一个一个拷贝到新空间,再释放旧空间,最后指向新空间。如果没有,直接指向新空间即可。
//reserve扩容 void reserve(size_t n) { size_t sz = size();//提前算出size()的大小,方便后续更新_finish if (n > capacity()) { T* tmp = new T[n]; if (_start)//判断旧空间是否有数据 { //不能用memcpy,因为memcpy是浅拷贝 for (size_t i = 0; i < size(); i++) { tmp[i] = _start[i];//将容器当中的数据一个个拷贝到tmp当中 } delete[] _start;//释放旧空间 } _start = tmp;//指向新空间 } //更新_finish和_endofstoage _finish = _start + sz; _endofstoage = _start + n; }
注意:
- 在扩容结束后要记得更新_finish和_endofstoage,这里的_finsh要加上原先的size()长度,要先用变量sz保存下来,否则后续扩容后会更改指针的指向由原先的_start变为tmp,若直接+ size()函数的返回值会导致结果为随机值。
- 不能使用memcpy进行数据拷贝,因为memcpy是浅拷贝,它会将一段内存空间中内容原封不动的拷贝到另外一段内存空间中,导致后续delete时拷贝过的数据一并给delete了,具体下篇博文详谈。
4.3 重新定义大小
- resize(int num); resize(int num.elem);//用elem填充
- 如果 n 小于当前容器的size(),则内容将减少到其前 n 个元素,删除超出(并销毁)的元素。
- 如果 n 大于当前容器 size(),则通过在末尾插入所需数量的元素以达到 n 的大小来扩展内容。若指定了 val,则新元素将初始化为 val 的副本,否则,它们将进行值初始化。
- 如果 n 也大于当前容器容量capacity(),则会自动重新分配分配的存储空间。
//resize //void resize(size_t n, T val = T()) void resize(size_t n, const T& val = T()) //利用T()调用默认构造函数的值进行初始化,这样写说明C++的内置类型也有自己的构造函数 { //如果 n > capacity()容量,就需要扩容 if (n > capacity()) { reserve(n); } //如果 n > size(),就需要把有效数据_finish到_start + n之间的数据置为缺省值val if (n > size()) { while (_finish < _start + n) { *_finish = val; _finish++; } } //如果 n < size(),更新有效数据到_start + n else { _finish = _start + n; } }
- 补充:C++的内置类型也有自己的构造函数和析构函数,这样才能更好的支持模板。
void test() { int i = 0; int j = int(); int k = int(1); cout << i << endl;//0 cout << j << endl;//0 cout << k << endl;//1 }
4.4 swap交换
直接调用库函数的swap去进行成员变量的交换即可。
//交换函数 void swap(vector<T>& v) { std::swap(_start, v._start); std::swap(_finish, v._finish); std::swap(_endofstoage, v._endofstoage); }
5. vector插入和删除
5.1 尾插
- push_back(elem)
先判断是否需要扩容,把尾插的值赋过去,再更新有效数据地址_finish即可:
void push_back(const T& x) { //检测是否需要扩容 if (_finish == _endofstoage) { size_t newcapcacity = capacity() == 0 ? 4 : capacity() * 2; reserve(newcapcacity); } *_finish = x; _finish++; }
这里push_back还可以复用下文实现好的insert进行尾插,当insert中的pos为_finish时,insert实现的就是push_back尾插。而_finish可以通过调用迭代器end函数来解决。
void push_back(const T& x) { //法二:复用insert insert(end(), x); //当insert中的参数pos为end()时,就是尾插 }
5.2 插入insert
首先要检查插入的位置是否越界,以及是否需要扩容。接着检测是否需要扩容。再挪动数据,最后把值插入进去。
- 注意
注意扩容以后,pos就失效了,要记得更新pos,否则会发生迭代器失效。可以通过设定变量n来计算扩容前pos指针位置和_start指针位置的相对距离,最后在扩容后,让_start再加上先前算好的相对距离n就是更新后的pos指针的位置了。其实这里还有一个迭代器失效的问题,具体是啥,后续专门出一篇迭代器失效的文章。下面给出完善修正后的insert:
//insert iterator insert(iterator pos, const T& x) { //检测参数合法性 assert(pos >= _start && pos <= _finish); //检测是否需要扩容 /*扩容以后pos就失效了,需要更新一下*/ if (_finish == _endofstoage) { size_t n = pos - _start;//计算pos和start的相对距离 size_t newcapcacity = capacity() == 0 ? 4 : capacity() * 2; reserve(newcapcacity); pos = _start + n;//防止迭代器失效,要让pos始终指向与_start间距n的位置 } //挪动数据 iterator end = _finish - 1; while (end >= pos) { *(end + 1) = *(end); end--; } //把值插进去 *pos = x; _finish++; return pos; }
5.3 尾删
首先判断_finish是否大于_start,若大于,直接_finsh--即可,否则啥也不需要操作。
void pop_back() { if (_finish > _start)//判断是否可以进行删除 { _finish--; } }
pop_back也可以复用下文的erase实现,当erase的参数为_finish时,实现的就是尾删,而_finish可以通过调用迭代器end()函数来解决。
void pop_back() { //法二:复用erase erase(end() - 1); //不能用end()--,因为end()是传值返回,返回的是临时对象,临时对象具有常性,不能自身++或--,因此要用end() - 1 }
5.4 erase删除
首先要检查删除位置pos的合法性,其次从pos + 1的位置开始往前覆盖即可删除pos位置,最后记得返回的值为删除位置的下一个位置,其实返回的就是pos,因为在pos删除后,下一个值会覆盖到pos的位置上。
//erase iterator erase(iterator pos) { //检查合法性 assert(pos >= _start && pos < _finish); //从pos + 1的位置开始往前覆盖,即可完成删除pos位置的值 iterator it = pos + 1; while (it < _finish) { *(it - 1) = *it; it++; } _finish--; return pos; }
- 补充说明:
- 一般vector删除数据,都不考虑缩容的方案,当size() < capacity() / 2 时,可以考虑开一个size()大小的新空间,拷贝数据,释放旧空间。缩容的本质是时间换空间。一般设计不会考虑缩容,因为实际比较关注时间效率,不是太关注空间效率,因为现在硬件设备空间都比较大,空间存储也比较便宜。
- erase也会存在失效,erase的失效是意义变了,或者不存在有效访问数据有效范围。
- 一般不会使用缩容的方案,那么erase的失效,一般也不存在野指针的失效。
后续专门推出一篇博文讲解迭代器失效。这里先给出结论:
- erase(pos)以后pos失效了,pos的意义变了,但是在不同平台下面对于访问pos的反应是不一样的,我们用的时候要以失效的角度去看待此问题。
- 对于insert和erase造成迭代器失效问题,linux的g++平台检查很佛系,基本靠操作系统本身野指针越界检擦机制。windows下VS系列检擦更严格一些,使用一些强制检擦机制,意义变了可能会检擦出来。
- 虽然g++对于迭代器失效检查时是非常佛系的,但是套在实际场景中,迭代器意义变了,也会出现各种问题。
5.5 clear清空数据
只需要把起始位置的指针_start赋给有效数据指针_finish即可完成数据的清空。
//clear清空数据 void clear() { _finish = _start; }
6.总代码
6.1 vector.h
#pragma once
#include<assert.h>
#include<iostream>
using namespace std;
namespace cpp
{
template<class T>
class vector
{
public:
typedef T* iterator;
typedef const T* const_iterator;
/*构造函数*/
//无参构造
vector()
:_start(nullptr)
, _finish(nullptr)
, _endofstoage(nullptr)
{}
//带参构造
template <class InputIterator>
vector(InputIterator first, InputIterator last)
: _start(nullptr)
, _finish(nullptr)
, _endofstoage(nullptr)
{
//将迭代器区间在[first, last)的数据一个个尾插到容器当中
while (first != last)
{
push_back(*first);
first++;
}
}
//用n个val来构造vector
vector(size_t n, const T& val = T())
: _start(nullptr)
, _finish(nullptr)
, _endofstoage(nullptr)
{
reserve(n);
for (size_t i = 0; i < n; i++)
{
push_back(val);
}
}
vector(int n, const T& val = T())
: _start(nullptr)
, _finish(nullptr)
, _endofstoage(nullptr)
{
reserve(n);
for (int i = 0; i < n; i++)
{
push_back(val);
}
}
//交换函数
void swap(vector<T>& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_endofstoage, v._endofstoage);
}
/*拷贝构造函数*/
//vector(const vector& v) 也可以这样写,但不推荐
vector(const vector<T>& v)
:_start(nullptr)
, _finish(nullptr)
, _endofstoage(nullptr)
{
vector<T> tmp(v.begin(), v.end());
swap(tmp);
}
/*赋值运算符重载*/
//vector& operator=(vector v) 也可以这样写,但不推荐
vector<T>& operator=(vector<T> v)
{
this->swap(v);
return *this;
}
/*析构函数*/
~vector()
{
if (_start)//避免释放空指针
{
delete[] _start;//释放容器所指向的空间
_start = _finish = _endofstoage = nullptr;//置空
}
}
/*容器访问相关函数*/
//迭代器
//begin
iterator begin()
{
return _start;
}
//end
iterator end()
{
return _finish;
}
//const版本迭代器
const_iterator begin() const
{
return _start;
}
//end
const_iterator end() const
{
return _finish;
}
//operator[]运算符重载
T& operator[](size_t pos)
{
assert(pos < size());//检测pos的合法性
return _start[pos];
}
//const版本的[]运算符重载
const T& operator[](size_t pos) const
{
assert(pos < size());//检测pos的合法性
return _start[pos];
}
/*空间增长问题*/
//size
size_t size() const //最好加上const,普通对象和const对象均可调用
{
return _finish - _start; //指针相减就能得到size的个数
}
//capacity
size_t capacity() const
{
return _endofstoage - _start;
}
//reserve扩容
void reserve(size_t n)
{
size_t sz = size();//提前算出size()的大小,方便后续更新_finish
if (n > capacity())
{
T* tmp = new T[n];
if (_start)//判断旧空间是否有数据
{
//不能用memcpy,因为memcpy是浅拷贝
for (size_t i = 0; i < size(); i++)
{
tmp[i] = _start[i];
}
delete[] _start;//释放旧空间
}
_start = tmp;//指向新空间
}
//更新_finish和_endofstoage
_finish = _start + sz;
_endofstoage = _start + n;
}
//resize
//void resize(size_t n, T val = T())
void resize(size_t n, const T& val = T()) //利用T()调用默认构造函数的值进行初始化,这样写说明C++的内置类型也有自己的构造函数
{
//如果 n > capacity()容量,就需要扩容
if (n > capacity())
{
reserve(n);
}
//如果 n > size(),就需要把有效数据_finish到_start + n之间的数据置为缺省值val
if (n > size())
{
while (_finish < _start + n)
{
*_finish = val;
_finish++;
}
}
//如果 n < size(),更新有效数据到_start + n
else
{
_finish = _start + n;
}
}
/*增加*/
//push_back
void push_back(const T& x)
{
//检测是否需要扩容
if (_finish == _endofstoage)
{
size_t newcapcacity = capacity() == 0 ? 4 : capacity() * 2;
reserve(newcapcacity);
}
*_finish = x;
_finish++;
/*
法二:复用insert
insert(end(), x); //当insert中的参数pos为end()时,就是尾插
*/
}
//insert
iterator insert(iterator pos, const T& x)
{
//检测参数合法性
assert(pos >= _start && pos <= _finish);
//检测是否需要扩容
/*扩容以后pos就失效了,需要更新一下*/
if (_finish == _endofstoage)
{
size_t n = pos - _start;//计算pos和start的相对距离
size_t newcapcacity = capacity() == 0 ? 4 : capacity() * 2;
reserve(newcapcacity);
pos = _start + n;//防止迭代器失效,要让pos始终指向与_start间距n的位置
}
//挪动数据
iterator end = _finish - 1;
while (end >= pos)
{
*(end + 1) = *(end);
end--;
}
//把值插进去
*pos = x;
_finish++;
return pos;
}
/*删除*/
//pop_back
void pop_back()
{
if (_finish > _start)
{
_finish--;
}
/*
法二:复用erase
erase(end() - 1);
//不能用end()--,因为end()是传值返回,返回的是临时对象,临时对象具有常性,不能自身++或--,因此要用end() - 1
*/
}
//erase
iterator erase(iterator pos)
{
//检查合法性
assert(pos >= _start && pos < _finish);
//从pos + 1的位置开始往前覆盖,即可完成删除pos位置的值
iterator it = pos + 1;
while (it < _finish)
{
*(it - 1) = *it;
it++;
}
_finish--;
return pos;
}
//clear清空数据
void clear()
{
_finish = _start;
}
private:
iterator _start; //指向容器的头
iterator _finish; //指向有效数据的尾
iterator _endofstoage;//指向容器的尾
};
}
6.2 test.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include<vector>
#include"vector.h"
void test()
{
int i = 0;
int j = int();
int k = int(1);
cout << i << endl;//0
cout << j << endl;//0
cout << k << endl;//1
}
void test_vector1()
{
cpp::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
cpp::vector<int>::iterator it = v.begin();
while (it != v.end())
{
cout << *it << " ";
it++;
}
cout << endl;
v.pop_back();
v.pop_back();
/*for (auto e : v)
{
cout << e << " ";
}*/
for (size_t i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
}
void test_vector2()
{
cpp::vector<int> v;
v.resize(10, -2);
for (auto e : v)
{
cout << e << " ";
}
}
void test_vector3()
{
//在所有的偶数前面插入2
cpp::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);
cpp::vector<int>::iterator it = v.begin();
while (it != v.end())
{
if (*it % 2 == 0)
{
//it = v.insert(it, 20);
it++;
}
it++;
}
for (auto e : v)
{
cout << e << " ";
}
}
//在所有的偶数前面插入2
/*v.push_back(5);
v.push_back(6);*/
void test_vector4()
{
cpp::vector<int> v;
//v.reserve(10);
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
cout << v.size() << ":" << v.capacity() << endl;
auto pos = find(v.begin(), v.end(), 2);
if (pos != v.end())
{
v.erase(pos);
}
cout << *pos << endl;
*pos = 10;
cout << *pos << endl << endl;
cout << v.size() << ":" << v.capacity() << endl;
for (auto e : v)
{
cout << e << " ";
}
}
namespace std
{
void test_vector5()
{
vector<int> v;
//v.reserve(10);
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
cout << v.size() << ":" << v.capacity() << endl;
auto pos = find(v.begin(), v.end(), 4);
if (pos != v.end())
{
v.erase(pos);
}
cout << *pos << endl;
*pos = 10;
cout << *pos << endl << endl;
cout << v.size() << ":" << v.capacity() << endl;
for (auto e : v)
{
cout << e << " ";
}
}
void test_vector6()
{
//删除所有的偶数
vector<int> v;
//v.reserve(10);
v.push_back(1);
v.push_back(2);
v.push_back(2);
v.push_back(2);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
auto it = v.begin();
while (it != v.end())
{
if (*it % 2 == 0)
{
it = v.erase(it);
}
else
{
it++;
}
}
for (auto e : v)
{
cout << e << " ";
}
}
}
void test_vector7()
{
//在所有的偶数前面插入2
cpp::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);
cpp::vector<int> v2(v.begin(), v.end());
for (auto e : v2)
{
cout << e << " ";//1 2 3 4 5 6
}
cout << endl;
string s("hello world");
cpp::vector<char> v3(s.begin(), s.end());
for (auto e : v3)
{
cout << e << " "; //h e l l o w o r l d
}
cout << endl;
cpp::vector<int> v4(v2);
for (auto e : v4)
{
cout << e << " ";//1 2 3 4 5 6
}
cout << endl;
v4.pop_back();
v4.pop_back();
v4.pop_back();
cpp::vector<int> v5;
v5 = v4;
for (auto e : v5)
{
cout << e << " ";//1 2 3 4 5 6
}
}
void test_vector8()
{
cpp::vector<int> v(10, 4);
for (auto e : v)
{
cout << e << " ";
}
}
void test_vector9()
{
cpp::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 (auto e : v)
{
cout << e << " ";
}
}
void test_vector10()
{
//在所有的偶数前面插入2
cpp::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);
cpp::vector<int>::iterator it = v.begin();
while (it != v.end())
{
if (*it % 2 == 0)
{
it = v.insert(it, 20);
it++;
}
it++;
}
for (auto e : v)
{
cout << e << " ";
}
}
void test1()
{
vector<int> v;
v.reserve(10);
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
cout << v.size() << ":" << v.capacity() << endl;
auto pos = find(v.begin(), v.end(), 2);
if (pos != v.end())
{
v.insert(pos, 20);
}
cout << *pos << endl;
}
void test2()
{
cpp::vector<int> v;
//v.reserve(10);
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
cout << v.size() << ":" << v.capacity() << endl;
auto pos = find(v.begin(), v.end(), 4);
if (pos != v.end())
{
v.erase(pos);
}
cout << *pos << endl;
*pos = 10;
cout << *pos << endl << endl;
cout << v.size() << ":" << v.capacity() << endl;
for (auto e : v)
{
cout << e << " ";
}
}
void test3()
{
std::vector<int> v;
//v.reserve(10);
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
cout << v.size() << ":" << v.capacity() << endl;
auto pos = find(v.begin(), v.end(), 4);
if (pos != v.end())
{
v.erase(pos);
}
cout << *pos << endl;
*pos = 10;
cout << *pos << endl << endl;
cout << v.size() << ":" << v.capacity() << endl;
for (auto e : v)
{
cout << e << " ";
}
}
void test4()
{
//删除所有的偶数
std::vector<int> v;
//v.reserve(10);
v.push_back(1);
v.push_back(2);
v.push_back(2);
v.push_back(2);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
auto it = v.begin();
while (it != v.end())
{
if (*it % 2 == 0)
{
it = v.erase(it);
}
else
{
it++;
}
}
for (auto e : v)
{
cout << e << " ";
}
}
namespace cpp
{
class Solution {
public:
// 核心思想:找出杨辉三角的规律,发现每一行头尾都是1,中间第[j]个数等于上一行[j-1]+[j]
vector<vector<int>> generate(int numRows) {
vector<vector<int>> vv;
// 先开辟杨辉三角的空间
vv.resize(numRows);
for (size_t i = 1; i <= numRows; ++i)
{
vv[i - 1].resize(i, 0);
// 每一行的第一个和最后一个都是1
vv[i - 1][0] = 1;
vv[i - 1][i - 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 - 1] + vv[i - 1][j];
}
}
}
return vv;
}
};
void test7()
{
vector<vector<int>> vv = Solution().generate(5);
for (size_t i = 0; i < vv.size(); ++i)
{
for (size_t j = 0; j < vv[i].size(); ++j)
{
cout << vv[i][j] << " ";
}
cout << endl;
}
}
}
int main()
{
/*cpp::vector<int> v;
size_t size = v.size();
size_t capacity = v.capacity();
cout << "size:" << size << endl;
cout << "capacity:" << capacity << endl;
v.push_back(1);
cout << "size:" << size << endl;
cout << "capacity:" << capacity << endl;
v.push_back(2);
v.push_back(3);
v.push_back(4);*/
//test_vector1();
//test();
//test_vector2();
//test_vector3();
//std::test_vector5();
//std::test_vector6();
//test_vector8();
//test_vector10();
//test2();
//test3();
//test4();
cpp::test7();
}