vector 向量容器
作为数组的一个泛化推广的 vector 容器,不仅可以进行数组一样的元素随机访问,还可以在容器的尾端插入新元素,是一个实现了 Random Access Container 和 Back Insertion Sequence 概念的模型
vector 是一种简单、高效的容器。在尾端插入和删除元素,算法时间复杂度为 O(1) 常数阶,其他元素的插入删除为 O(n) 线型阶,其中 n 为 vector 容器的元素个数。 vector 具有自动的内存管理功能,对于元素的插入和删除,可动态调整所占用的内存空间。
vector 容器的 C++ 标准头文件为 vector, 因此,必须将宏语句 "#include <vector>" 包含到cpp文件中,才可正确编译使用。
创建 vector 对象
如下4个vector的构造函数,均可创建一个vector对象
1. vector(const A& a = A())
创建一个空的 vector 对象,A 是内存分配器,此参数可以省略,相当于一个 vector() 的调用。
例如,下面一行代码创建了一个 vector 对象 vInt
vector<int> vInt;
2. vector(size_type n)
创建一个具有 n 个元素的 vector 对象,每个 vector 元素具有它的类型下的默认值。此时, n 个 vector 元素的内存空间已被分配。
例如,下面一行代码创建了具有 10 个元素的 vector 对象 vDou,每个元素的默认值为 0.0
vector<double> vDou(10);
3. vector(size_type n, const T& value)
创建一个具有 n 个元素的 vector 对象,每个元素具有初始值 value 。
例如,下面一行代码创建了一个具有 10 个元素的 vector 对象 vDou, 每个元素的初始值为 9.3
vector<double> vDou(10, 9.3);
4. vector(const vector&)
通过拷贝一个 vector 对象的各个元素值,创建一个新的 vector 对象。
例如,下面使用 v1 对象 创建 v2 对象,此时,v2 对象的 5 个元素也具有字符值 "K"
vector<char> v1(5,'K');
vector<char> v2(v1);
这是第五种创建方法
5. vector(const InputInerator first, const InputIterator last, const A& a = A())
InputIterator 为输入迭代器,通过拷贝迭代器区间 [first, last ) 的元素值,创建一个新的vector对象,内存分配器可省略。
例如,利用 int 数组 iArray 各元素值,创建了 vector 对象 v
int iArray[] = {11, 13, 19, 23, 28};
vector<int> v(iArray, iArray + 5);
1 // 创建对象之后,再赋值的方法, assign 函数 2 vector<int> vecIntA, vecIntB, vecIntC; 3 int iArray[] = {0,1,2,3,4}; 4 vecIntA.assign(iArray,iArray+5); 5 6 vecIntB.assign( vecIntA.begin(), vecIntA.end() ); //用其它容器的迭代器作参数。 7 8 vecIntC.assign(3,9); // 在对象vecIntC中添加 3 个元素,元素值值为 9 9 10 vector<int> vecIntD; // 直接赋值也可以,这是深拷贝,赋值之后,vecIntA 中的值改变,不会影响vecIntD 11 vecIntD = vecIntA;
初始化赋值
vector 提供的 push_back() 函数,常用来进行 vector 容器的初始化。 push_back() 函数在容器的尾端插入新元素。
元素的遍历访问
vector 的元素可以采用数组,.at() 函数或者迭代器的方式进行遍历访问。
1 #include <vector> 2 #include <iostream> 3 using namespace std; 4 int main() 5 { 6 vector<int> vInt; 7 vInt.push_back(20); 8 vInt.push_back(26); 9 vInt.push_back(39); 10 11 // cout << "VInt【2】 = " << vInt[2] <<endl; 12 // cout << "VInt【3】 = " << vInt[3] <<endl; 13 // cout << "VInt【4】 = " << vInt[4] <<endl << endl << endl; 14 // 15 // cout << "VInt【2】 = " << vInt.at(2) <<endl; 16 // cout << "VInt【3】 = " << vInt.at(3) <<endl; 17 // cout << "VInt【4】 = " << vInt.at(4) <<endl; 18 19 20 for (int i=0; i<vInt.size(); i++) 21 { 22 // vInt[i] 为数组方式的访问。访问越界时,不产生异常 23 //cout << "VInt【" << i << "】 = " << vInt[i] <<endl; 24 25 // vInt.at(i) 为函数访问方式。当访问越界时,会抛出异常 26 cout << "VInt【" << i << "】 = " << vInt.at(i) <<endl; 27 } 28 29 30 return 0; 31 }
1 #include <vector> 2 #include <iostream> 3 using namespace std; 4 int main() 5 { 6 vector<int> vInt; 7 vInt.push_back(20); 8 vInt.push_back(26); 9 vInt.push_back(39); 10 11 // 起始 和 末尾 迭代器值 12 vector<int>::iterator i, iend; 13 iend = vInt.end(); 14 int j; 15 for (i=vInt.begin(), j=0; i!=iend; i++, j++) 16 { 17 cout << "v[" << j << "] = " << *i << endl; 18 } 19 20 return 0; 21 }
1 /* 解释: 2 不同于在 vector 容器尾部添加元素的 push_back 函数, insert 函数可以在任意位置插入元素。 3 由于插入时,需要先将插入位置后面的元素移位,以空出一个位置进行插入,因此,insert 函数的执行比较 push_back 函数较为耗时。 4 */ 5 6 -------------------------------- 在任意位置插入 vector 元素 7 #include <vector> 8 #include <iostream> 9 using namespace std; 10 int main() 11 { 12 vector<int> vInt; 13 vInt.push_back(6); 14 vInt.push_back(7); 15 vInt.push_back(8); 16 vInt.push_back(10); 17 // 在元素 10 的前面插入 9 18 vInt.insert(vInt.begin() + 3, 9); 19 // 插入 5 为首元素 20 vInt.insert(vInt.begin(), 5); 21 // 插入 11 为末元素 22 vInt.insert(vInt.end(), 11); 23 24 for (int i=0; i<vInt.size(); i++) 25 { 26 cout << "V[" << i << "]=" << vInt[i] << endl; 27 } 28 29 return 0; 30 }
1 ---------------------------------------- 利用 erase 函数删除 vector 元素 2 #include <iostream> 3 #include <vector> 4 using namespace std; 5 class MyAnimal 6 { 7 public: 8 char* m_name; 9 int m_age; 10 public: 11 MyAnimal(char* name, int age) 12 { 13 this->m_name = name; 14 this->m_age = age; 15 } 16 ~MyAnimal(){} 17 18 }; 19 20 int main() 21 { 22 MyAnimal* pDog = new MyAnimal("dog", 1); 23 MyAnimal* pMonkey = new MyAnimal("monkey", 2); 24 MyAnimal* pChicken = new MyAnimal("chicken", 3); 25 MyAnimal* pSnake = new MyAnimal("snake", 4); 26 27 // v 将存放各对象的地址 28 vector<MyAnimal*> v; 29 v.push_back(pDog); 30 v.push_back(pMonkey); 31 v.push_back(pChicken); 32 v.push_back(pSnake); 33 34 // 物理删除 pMonkey 所指的对象 35 delete pMonkey; 36 // 删除第 2 个元素,即删除 vector 容器的元素 pMonkey 37 v.erase(v.begin()+1); 38 vector<MyAnimal*>::iterator i, iend; 39 iend = v.end(); 40 for (i=v.begin(); i!=iend; ++i) 41 { 42 cout << (*i)->m_name << ' ' << (*i)->m_age <<endl; 43 } 44 // 清除所有 vector 元素 45 v.clear(); 46 cout << " 执行 clear() " << endl << "vector 元素已全部清除。" <<endl; 47 48 return 0; 49 }
1 -------- erase 的补充 2 vecInt是用vector<int>声明的容器,现已包含按顺序的1,3,2,3,3,3,4,3,5,3元素。现要求删除容器中所有等于3的元素。 3 for(vector<int>::iterator it=vecInt.begin(); it!=vecInt.end(); ) //小括号里不需写 ++it 4 { 5 if(*it == 3) 6 { 7 it = vecInt.erase(it); //以迭代器为参数,删除元素3,并把数据删除后的下一个元素位置返回给迭代器。 8 //此时,不执行 ++it; 9 } 10 else 11 { 12 ++it; 13 } 14 }
1 -------------------------------------------------- 反向遍历 vector 的元素 2 #include <vector> 3 #include <iostream> 4 using namespace std; 5 int main() 6 { 7 vector<int> vInt; 8 vInt.push_back(1); 9 vInt.push_back(3); 10 vInt.push_back(5); 11 vInt.push_back(7); 12 vInt.push_back(9); 13 // 元素的反向遍历访问 14 vector<int>::reverse_iterator ri,riend; 15 riend = vInt.rend(); 16 for (ri=vInt.rbegin(); ri!=riend; ++ri) 17 { 18 cout << *ri << endl; 19 } 20 21 return 0; 22 }
1 -------------------------------------------------- 两个 vector 容器元素的交换 2 #include <vector> 3 #include <iostream> 4 using namespace std; 5 void print(vector<int>& vInt); 6 int main() 7 { 8 //vIntA 9 vector<int> vIntA; 10 vIntA.push_back(11); 11 vIntA.push_back(12); 12 vIntA.push_back(13); 13 cout << " vIntA = "; 14 print(vIntA); 15 16 //vIntB 17 vector<int> vIntB; 18 vIntB.push_back(90); 19 vIntB.push_back(92); 20 cout<< " vIntB = "; 21 print(vIntB); 22 23 // vIntA 与 vIntB 交换 24 swap(vIntA, vIntB); 25 cout << "vIntA 与 vIntB 交换后" << endl; 26 cout << "vIntA ="; 27 print(vIntA); 28 cout << "vIntB ="; 29 print(vIntB); 30 31 return 0; 32 } 33 34 // vector 元素打印 35 void print(vector<int>& v) 36 { 37 for (int i=0; i<v.size(); i++) 38 cout<< v[i] << " " ; 39 cout << endl; 40 }
1 /* 解释: 2 1. bool empty() 判断容器 vector 是否为空,若容器没有一个元素则返回 true, 否则返回 false 3 2. size_type size() 当前 vector 容器的实际元素个数 4 3. size_type max_size() 系统所允许的 vector 容器的最大元素个数 5 4. size_type capacity() 当前可容纳的 vector 元素个数 6 5. reference front() vector容器的首元素(引用),要求 vector 不为空 7 6. reference back() vector容器的末元素(引用),要求 vector 不为空 8 7. void pop_back() 与 push_back() 函数相反,pop_back() 函数用于删除末尾的一个容器元素 9 */ 10 11 -------------------------------- vector 的其他常用函数 12 #include <vector> 13 #include <iostream> 14 using namespace std; 15 void print(vector<int>& v); 16 int main() 17 { 18 vector<int> vInt; 19 print(vInt); 20 // 添加 5 个元素 21 vInt.push_back(1); 22 vInt.push_back(2); 23 vInt.push_back(3); 24 vInt.push_back(4); 25 vInt.push_back(5); 26 print(vInt); 27 28 // 再添加 4 个元素 29 vInt.push_back(6); 30 vInt.push_back(7); 31 vInt.push_back(8); 32 vInt.push_back(9); 33 print(vInt); 34 35 // 调整 vector 数据空间大小 36 vInt.reserve(30); 37 print(vInt); 38 39 return 0; 40 } 41 42 void print(vector<int>& v) 43 { 44 cout << "----------------------" << endl; 45 cout << "empty = " << v.empty()<< endl; 46 cout << "size = " << v.size()<< endl; 47 cout << "max_size = " << v.max_size()<< endl; 48 cout << "capacity = " << v.capacity()<< endl; 49 50 }
------------ vector 小结:
vector 向量容器是一个实现数据线型存储的泛型类,除了可以使用数组方式进行元素访问外,还可以利用前向和反向迭代器
iterator/reverse_iterator ,以及 push_back 、 begin 、 end 、 erase 和 clear 等函数,对容器元素进行插入、遍历和删除操作。
vector尾部添加或移除元素非常快速。但是在中部或头部插入元素或移除元素比较费时
vector 缺点: vector 不适合那种 【容器元素在任意位置进行 插入、删除 操作非常频繁】 的情况
vector 优点: 看最前面的介绍