目录
1.vector
1.1介绍
vector是一个可变长度的数组(也被称为动态数组),它允许用户随时增加或移除元素。
注意:在局部区域中(例如局部函数内部)创建vector数组,实际上是在堆空间中进行的。
然而,在局部区域创建数组是在栈空间中进行的,而栈空间相对较小。如果创建一个非常大的数组,可能会导致栈溢出。
因此,在局部区域中不应该创建过大的数组,但是可以创建大长度的vector。
头文件:
#include <vector>
定义一维数组:
vector<类型> a; //定义了一个名为a的一维数组,数组存储“类型”类型数据
指定长度和初始值的初始化:
vector<int> v(n);// 定义一个长度为n的数组,初始值默认为0,下标范围[0, n - 1]
vector<int> v(n, 1);// v[0] 到 v[n - 1]所有的元素初始值均为1
//指定数组长度之后(指定长度后的数组就相当于正常的数组了)
初始化
vector<int> a{1, 2, 3, 4, 5};//数组a中有五个元素,数组长度就为5
Copy初始化
vector<int> a(n + 1, 0);
vector<int> b(a);
vector<int> c = a;
二维初始化
vector<int> v[5];//定义可变长二维数组
//注意:行不可变(只有5行), 而列可变,可以在指定行添加元素
在C++中,你可以创建一个名为
v
的二维数组,它由5个vector<int>
类型的元素组成。这个数组的每一行都可以根据需要动态地调整其长度,因为没有预先设定每个vector<int>
的大小。因此,v
实际上是一个具有固定行数但可变列数的二维结构。对于这样的数据结构,你可以执行各种操作,例如添加、删除或修改其中的元素。v[1].push_back(2); v[2].push_back(3);
行列均可变
//初始化二维均可变长数组
vector<vector<int>> v;//定义一个行和列均可变的二维数组
应用:可以在
v
数组里面装多个数组vector<int> t1{1, 2, 3, 4}; vector<int> t2{2, 3, 4, 5}; v.push_back(t1); v.push_back(t2); v.push_back({3, 4, 5, 6}) // {3, 4, 5, 6}可以作为vector的初始化,相当于一个无名vector
始化一个大小为n+1行和m+1列的矩阵,其中每个元素的初始值均为0。
vector<vector<int>> a(n + 1, vector<int>(m + 1, 0));
C++17或C++20支持的形式(不常用),与上面相同的初始化。
vector a(n + 1, vector(m + 1, 0));
1.2函数
在掌握了初始化可变数组的定义方法之后,接下来的任务便是学习如何进行数据的添加、删除和修改操作。
c指定为数组名称.
代码 | 含义 |
c.front() | 返回第一个数据 |
c.back() | 返回数组中的最后一个数据 |
c.pop_back() | 删除最后一个数据 |
c.size() | 返回c的大小 |
c.push_back(element) | 在尾部加一个数 |
c.clear() | 清除c中的所有数 |
c.resize(n, v) | 改变数组大小为n ,n 个空间数值赋为v ,如果没有默认赋值为0 |
c.insert(it, x) | 向任意迭代器it 插入一个元素x |
c.insert(c.begin() + 2,-1) | 将-1 插入c[2] 的位置 |
c.erase(first,last) | 删除[first,last) 的所有元素 |
c.begin() | 返回首元素的迭代器(通俗来说就是地址) |
c.end() | 返回最后一个元素后一个位置的迭代器(地址) |
c.empty() | 判断是否为空,为空返回真,反之返回假 |
注意:
end()函数返回的是最后一个元素之后的位置地址,而不是最后一个元素的地址,这是所有STL容器的共同特性。在使用vi.resize(n, v)方法时,如果之前已经为vi设置了大小为pre。当pre大于n时,即数组的大小减小了,数组将保留前n个元素,这n个元素的值保持不变,而不是全部变为v。当pre小于n时,即数组的大小增大了,数组将在末尾添加n - pre个值为v的新元素。换句话说,这个初始值v仅对新添加的元素有效。
#include<bits/stdc++.h> using namespace std; void out(vector<int> &a) { for (auto &x: a) cout << x << " "; cout << "\n"; } int main() { vector<int> a(5, 1); out(a); // 1 1 1 1 1 a.resize(10, 2); out(a); // 1 1 1 1 1 2 2 2 2 2 a.resize(3, 3); out(a); // 1 1 1 return 0; }
排序
使用sort
排序要: sort(c.begin(), c.end());
对所有元素进行排序,如果要对指定区间进行排序,可以对
sort()
里面的参数进行加减改动。
vector<int> a(n + 1);
sort(a.begin() + 1, a.end()); // 对[1, n]区间进行从小到大排序
1.3 访问
共三种方法:
- 下标法 : 和普通数组一样
注意:一维数组的下标是从 0
到 v.size()-1
,访问之外的数会出现越界错误
- 迭代器法 : 类似指针一样的访问 ,首先需要声明迭代器变量,和声明指针变量一样,可以根据代码进行理解(附有注释)。
vector<int> vi; //定义一个vi数组
vector<int>::iterator it = vi.begin();//声明一个迭代器指向vi的初始位置
- 使用auto :非常简便,但是会访问数组的所有元素(特别注意0位置元素也会访问到)
1.3.1 下标访问
直接和普通数组一样进行访问即可。
//添加元素
for(int i = 0; i < 5; i++)
vi.push_back(i);
//下标访问
for(int i = 0; i < 5; i++)
cout << vi[i] << " ";
cout << "\n";
1.3.2 迭代器访问
像指针那样,迭代器扮演了指针的角色。
vector<int> vi{1, 2, 3, 4, 5};
//迭代器访问
vector<int>::iterator it;
// 相当于声明了一个迭代器类型的变量it
// 通俗来说就是声明了一个指针变量
- 方式一:
vector<int>::iterator it = vi.begin();
for(int i = 0; i < 5; i++)
cout << *(it + i) << " ";
cout << "\n";
- 方式二
vector<int>::iterator it;
for(it = vi.begin(); it != vi.end();it ++)
cout << *it << " ";
//vi.end()指向尾元素地址的下一个地址
// 或者
auto it = vi.begin();
while (it != vi.end()) {
cout << *it << "\n";
it++;
}
1.3.3 智能指针
仅能完成数组的完整遍历,若需对特定内容进行遍历,则必须采用其他方式。auto 具备自动确定并捕获数据类型的能力。
// 1. 输入
vector<int> a(n);
for (auto &x: a) {
cin >> x; // 可以进行输入,注意加引用
}
// 2. 输出
vector<int> v;
v.push_back(12);
v.push_back(241);
for(auto val : v) {
cout << val << " "; // 12 241
}
请注意,vector中的vi[i]与(vi.begin() + i)具有相同的功能,类似于指针。vector和string的STL容器支持使用(it + i)进行元素访问,其他容器可能也支持这种访问方式,尽管使用较少,但你可以尝试一下。
就到这啦,大家再见,多多支持我啊QwQ,谢谢....