爱吃喵的鲤鱼
个人主页
文章目录
- 前言
- 一、pandas是什么?
- 二、使用步骤
- 1.引入库
- 2.读入数据
- 总结
前言
我们已经 学习了string在来实现vector会发现他们两的结构很像,而string只支持存储字符串,vector支持任意类型;
一、vector是什么?
vector和string都一样,是c++的容器,两个的差别在于vector存储的是任意类型,string是字符串。底层结构也有所不同,string数据结构和数组相似,而vector使用3个指针控制的。
二、vector的使用
2.常用的函数代码演示
1、迭代器的使用
void func(const vector<int>& vv)
{
vector<int>::const_iterator it = vv.begin();
for (size_t i = 0; i < vv.size(); i++)
{
cout << vv[i] << " ";
}
cout << endl;
while (it != vv.end())
{
cout << *it << " ";
it++;
}
cout << endl;
for (auto i : vv)
{
cout << i << " ";
}
cout << endl;
}
其实大家经常使用的范围for也是迭代器的使用;
2、常用的修改器
vector<int> vv;
vv.push_back(1);
vv.push_back(2);
vv.push_back(3);
vv.push_back(4);
vector<int>::iterator pos = find(vv.begin(), vv.end(), 2);
if (pos == vv.end())
{
vv.insert(pos, 30);
}
for (auto i : vv)//打印元素
{
cout << i << " ";
}
cout << endl;
vv.resize(20,0);//开20个空间并且初始化
for (auto i : vv)//打印元素
{
cout << i << " ";
}
cout << endl;
vv.push_back(20);//尾插
for (auto i : vv)//打印元素
{
cout << i << " ";
}
cout << endl;
vv.pop_back();
vv.pop_back();
vv.pop_back();
for (int i = 0; i < 10; i++)//循环尾删10次
{
vv.pop_back();
}
for (auto i : vv)//打印元素
{
cout << i << " ";
}
cout << endl;
auto it = vv.begin();
//删除偶数
while (it != vv.end())
{
if (*it % 2 == 0)
{
it = vv.erase(it);//删除it位置元素
}
else
it++;
}
for (auto i : vv)
{
cout << i << " ";
}
}
3、容量
已经在上面两类中体现了
三、底层模拟实现
1、vector构架
template<class T>//因为vector可以容下任意类型,所以我们构建了一个模板类
class vector
{
public:
typedef T* iterator;//对迭代器的声名
typedef const T* const_iterator;//对const迭代器的声名
vector()//构造函数
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{}
~vector()//析构函数
{
delete[]_start;
_start = _finish = _end_of_storage = nullptr;
}
vector(size_t n,const T& val=T())//构造函数
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
for (size_t i = 0; i < n; i++)
{
push_back(val);
}
}
vector(int n, const T& val = T())//构造函数
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
for (size_t i = 0; i < n; i++)
{
push_back(val);
}
}
vector(const vector<T>& v)//拷贝构造
{
//reserve(capacity());
_start = new T[capacity()];
//memcpy(_start, v._start, sizeof(T)*v.size());//
for (size_t i = 0; i < v.size(); i++)
{
_start[i] = v._start[i];
}
_finish = _start + v.size();
_end_of_storage = _start + v.capacity();
}
private:
//左闭右开区间
iterator _start;
iterator _finish;
iterator _end_of_storage;
};
在我们的拷贝构造中涉及了一个深浅拷贝问题;
什么是深浅拷贝 ?
浅拷贝只是对成员变量进行了拷贝
浅拷贝就是我们只对一块内存空间的地址进行拷贝,这个时候就会有两个指针变量指向了同一块空间,当我们对第一个成员进行析构时,这空空间已经被释放了,第二个变量再来这里析构就会让程序崩溃;
深拷贝是两块不同的空间
深拷贝是在开辟一块空间,将原有内存中的数据一个个的拷贝到新空间中;
2、vector的迭代器函数
bool empty()//判断是否为空
{
return _start == _finish;
}
size_t capacity() const
{
return _end_of_storage - _start;
}
size_t size() const
{
return _finish - _start;
}
const T& operator[](size_t pos) const
{
assert(pos < size());
return _start[pos];
}
size_t capacity()
{
return _end_of_storage - _start;
}
size_t size()
{
return _finish - _start;
}
T& operator[](size_t pos)
{
assert(pos < size());
return _start[pos];
}
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const iterator begin() const
{
return _start;
}
const iterator end() const
{
return _finish;
}
迭代器中判断大小主要用的是地址-地址,因为一段连续的空间,地址-地址就是它的大小;
这些函数在后面使用时,我们会用到const的类型,所以构造了const的函数
3、修改器的模拟实现
iterator insert(iterator pos, const T& val = T())//在任意位置插入
{
assert(pos >= _start);
assert(pos <= _finish);
if (_finish == _end_of_storage)
{
size_t len = pos - _start;
reserve(capacity() == 0 ? 4 : capacity() * 2);
pos = _start + len;
}
iterator end = _finish - 1;//没有这个会有迭代器失效,就是构成野指针
while (end >= pos)
{
*(end + 1) = *end;
end--;
}
*pos = val;
_finish++;
return pos;//以后还可以在次使用
}
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)
{
*_finish = val;
++_finish;
}
}
}
iterator erase(iterator pos)//erase不在访问这块空间
{
assert(pos < _finish);
assert(pos >= _start);
iterator start = pos + 1;
while (start != _finish)
{
*(start-1) = *start;
start++;
}
_finish--;
return pos;
}
void reserve(size_t n)//开辟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 < size(); i++)
{
_start[i] = tmp[i];
}*/
delete[] _start;
}
_start = tmp;
_finish = tmp + sz;
_end_of_storage = tmp + n;
}
}
void push_back(const T& x)//尾插
{
if (_finish == _end_of_storage)
{
reserve(capacity() == 0 ? 4 : capacity() * 2);
}
*_finish = x;
_finish++;
}
void pop_back()//尾删
{
assert(!empty());
_finish--;
}