上次我们聊到了顺序容器与关联容器的概念,也简要总结了STL中主要容器的分类,同时也对list具体的使用与实现进行了描述,这次我们关注vector
vector字面意思很好理解,向量!这样我们可以直接得知它属于一种顺序容器,那么意味着他在内存上的分布是连续的,那么我们顺理成章的可以想到其内部是用数组来实现,在末尾增加或者删除元素所需时间与元素数目无关,在中间或者开头增加或者删除元素所需时间是随元素数目呈线性变化,(意味着数据量越大,速度越慢,这也是vector的弊端之一)
常用方法
//1.定义和初始化
vector<int> vec1; //默认初始化,vec1为空
vector<int> vec2(vec1); //使用vec1初始化vec2
vector<int> vec3(vec1.begin(),vec1.end());//使用vec1初始化vec2
vector<int> vec4(10); //10个值为0的元素
vector<int> vec5(10,4); //10个值为4的元素
//2.常用操作方法
vec1.push_back(100); //尾部添加元素
int size = vec1.size(); //元素个数
bool isEmpty = vec1.empty(); //判断是否为空
cout<<vec1[0]<<endl; //取得第一个元素
vec1.insert(vec1.end(),5,3); //从vec1.back位置插入5个值为3的元素
vec1.pop_back(); //删除末尾元素
vec1.erase(vec1.begin(),vec1.begin()+2);//删除vec1[0]-vec1[2]之间的元素,不包括vec1[2]其他元素前移
cout<<(vec1==vec2)?true:false; //判断是否相等==、!=、>=、<=...
vector<int>::iterator iter = vec1.begin(); //获取迭代器首地址
vector<int>::const_iterator c_iter = vec1.begin(); //获取const类型迭代器
vec1.clear(); //清空元素
//3.遍历
//下标法
int length = vec1.size();
for(int i=0;i<length;i++)
{
cout<<vec1[i];
}
cout<<endl<<endl;
//迭代器法
vector<int>::iterator iter = vec1.begin();
for(;iter != vec1.end();iter++)
{
cout<<*iter;
}
总结一下vector
1、占据一块连续的内存空间;
2、内部实现是通过管理了一个指针,只是当内存空间不够时,会重新分配一块更大的内存空间,通常是将容量扩大一倍;
3、vector对尾部操作很方便,对头部或者插入都需要O(n)的时间复杂度;
4.采用模板实现泛型类vector,为了支持大多数的编译器,将实现文件全部放在头文件中,不采用分离编译的方式
简单实现(C++)
MyVector.h
#pragma once
#include<vector>
#include<algorithm>
//void test_vector() {
// vector<int> v1;
// v1.push_back(1);
// v1.push_back(2);
// v1.push_back(3);
// v1.push_back(4);
// v1.push_back(5);
// v1.push_back(66);
//
// print_vector(v1);
//
// //删除偶数
// vector<int>::iterator it1 = v1.begin();
// while (it1 != v1.end()) {
// if (*it1 % 2 == 0) {
// it1 = v1.erase(it1);
// }
// else {
// ++it1;
// }
// }
// print_vector(v1);
//
//
// //找到5的位置,在它前面插入一个30
// vector<int>::iterator pos1 = find(v1.begin(), v1.end(), 5);
// v1.insert(pos1, 30);
//
// print_vector(v1);
//
// //删除30
// pos1 = find(v1.begin(), v1.end(), 30);
// v1.erase(pos1);
// print_vector(v1);
//}
//
//void test_vector1() {
// vector<int> v1;
// v1.push_back(1);
// v1.push_back(2);
// v1.push_back(3);
// v1.push_back(4);
// v1.push_back(5);
// cout << "Size=" << v1.size() << endl;
// cout << "Capacity=" << v1.capacity() << endl;
// print_vector(v1);
//
// v1.resize(2);
// cout << "Size=" << v1.size() << endl;
// cout << "Capacity=" << v1.capacity() << endl;
// print_vector(v1);
//
// v1.resize(3, 5);
// cout << "Size=" << v1.size() << endl;
// cout << "Capacity=" << v1.capacity() << endl;
// print_vector(v1);
//
//
// v1.resize(10, 10);
// cout << "Size=" << v1.size() << endl;
// cout << "Capacity=" << v1.capacity() << endl;
// print_vector(v1);
// //resize和resever的作用与区别?
// //resize(),设置大小(size);
// //reserve(),设置容量(capacity);
// //打个比方:正在建造的一辆公交车,车里面可以设置40个座椅(reserve(40);),这是它的容量,但并不是说它里面就有了40个座椅,只能说明这部车内部空间大小可以放得下40张座椅而已。而车里面安装了40个座椅(resize(40);),这个时候车里面才真正有了40个座椅,这些座椅就可以使用了。
//
// //1.capacity 容器在分配新的存储空间之前能存储的元素总数,只是设置容器容量大小,但并没有真正分配内存。
// //2. size 指当前容器所存储的元素个数,也是分配容器的内存大小,
//
// //1).reserve表示容器预留空间,但并不是真正的创建对象,需要通过insert()或push_back()等创建对象。
// //resize既分配了空间,也创建了对象。
// //2).reserve只修改capacity大小,不修改size大小,
// //resize既修改capacity大小,也修改size大小。
// //3).两者的形参个数不一样。
// //resize带两个参数,一个表示容器大小,一个表示初始值(默认为0)
// //reserve只带一个参数,表示容器预留的大小。
//
// //vector<int> v1;
// //v1.push_back(1);
// //v1.push_back(2);
// //v1.push_back(3);
// //v1.push_back(4);
// //cout<<"Size = "<<v1.size()<<endl;
// //cout<<"Capacity = "<<v1.capacity()<<endl;
//
// //v1.reserve(2);
// //cout<<"Size = "<<v1.size()<<endl;
// //cout<<"Capacity = "<<v1.capacity()<<endl;
//
// //v1.reserve(100);
//
// //cout<<"Size = "<<v1.size()<<endl;
// //cout<<"Capacity = "<<v1.capacity()<<endl;
//
//
// //print_vector(v1);
//
// vector<int> v1;
// v1.push_back(1);
// cout << "Capacity = " << v1.capacity() << endl;
// v1.push_back(2);
// cout << "Capacity = " << v1.capacity() << endl;
// v1.push_back(3);
// cout << "Capacity = " << v1.capacity() << endl;
// v1.push_back(4);
// cout << "Capacity = " << v1.capacity() << endl;
// v1.push_back(5);
// cout << "Capacity = " << v1.capacity() << endl;
// v1.push_back(6);
// cout << "Capacity = " << v1.capacity() << endl;
// v1.push_back(7);
// cout << "Capacity = " << v1.capacity() << endl;
// print_vector(v1);
//}
//
//void print_vector(const vector<int>& v) {
// vector<int>::const_iterator it = v.begin();
// while (it != v.end()) {
// cout << *it << " ";
// ++it;
// }
// cout << endl;
//}
//
template<class T>
class Vector {
public:
typedef T* Iterator;
Vector()
:_start(NULL)
,_finish(NULL)
,_endOfStorage(NULL)
{}
~Vector(){
if (_start){
delete[] _start;
_start = _finish = _endOfStorage = NULL;
}
}
//Resize改变容器大小,且再创建对象
//第一个参数容器新的大小,第二个参数是要插入的元素,如果省略掉默认构造
void Resize(size_t n, const T& val = T()) {//??
if (n > Capacity()) {
Expand();
}
size_t size = Size();
if (n < size)
{
_finish = _start + n;
}
else
{
for (size_t i = 0; i < n - size; ++i) {
PushBack(val);
}
}
}
void Reserve(size_t n) {//改变预留空间,空间内并没有创建元素对象
Expand(n);
}
void PopBack() {
assert(_finish > _start);
--_finish;
}
void PushBack(const T& x) {
if (_finish == _endOfStorage) {
size_t capacity = Capacity();
size_t n = capacity == 0 ? 3 : 2 * capacity;//如果容器_start==_finish==_endOfStorage;,则capacity设为3,并且扩容至3,否则扩容原来容量的二倍
Expand(n);
}
*_finish = x;
++_finish;
}
bool isEmpty() {//判断Vector是否为空,
return Size() == 0;//返回0代表不为空,反回非0代表为空
}
Iterator Begin() {
return _start;
}
Iterator End() {
return _finish;
}
size_t Size() {
return _finish - _start;
}
size_t Capacity() {
return _endOfStorage - _start;
}
void Expand(size_t n) {
size_t capacity = Capacity();
size_t size = Size();
//扩容时,需要创建一个新数组,然后将原Vector拷贝进来
if (n > capacity) {
T* tmp = new T[n];
for (size_t i = 0; i < size; ++i) {
tmp[i] = _start[i];
}
delete[] _start;
_start = tmp;
_finish = _start + size;
_endOfStorage = _start + n;
}
}
T& operator[](size_t index) {
assert(index < Size());
return _start[index];
}
const T& operator [](size_t index)const {
assert((index < Size));
return _start[index];
}
T &operator=(const T& pos) {
if (this != pos) {
delete[] _start;//销毁原来的内存空间
Size() = pos.Size();
Capacity() = pos.Capacity();
T = new T[Capacity()];//重新分配内存空间
//进行深拷贝
for(int i=0;i<pos.Size;++i){
T[i] = pos.T[i];
}
}
return *this;
}
protected:
Iterator _start;
Iterator _finish;
Iterator _endOfStorage;
};
void TestVector()
{
Vector<int> v;
int ret = v.isEmpty();
cout << ret << endl;
v.PushBack(1);
v.PushBack(2);
v.PushBack(3);
v.PushBack(4);
Vector<int>::Iterator it = v.Begin();
while (it != v.End())
{
cout << *it << " ";
++it;
}
cout << endl;
for (size_t i = 0; i < v.Size(); ++i)
{
cout << v[i] << " ";
}
cout << endl;
int ret1 = v.isEmpty();
cout << ret1 << endl;
}
test.cpp
1
1、只实现了部分函数的功能,但是类似的可以定义其他的函数;
2、迭代器只是采用定义为指针的方式,这种方式比较简单,但是不能实现迭代器完全的功能。不过迭代器的本质也是将这个指针封装成一个类。