vector动态数组
中等5vector动态数组——像魔法铅笔盒一样方便的容器
你有没有遇到过这种情况:写作业时要记下全班同学的成绩,但一开始不知道有多少个同学?如果使用普通数组,必须提前定好大小,比如“最多50人”,但万一有51个人,数组就装不下了;或者只有10个人,却浪费了40个空位。C++里的 vector动态数组 就像一个神奇的铅笔盒,它可以根据你放进去的铅笔数量自动变长或变短——放多少支铅笔,盒子就多大,不多不少刚刚好!
一、什么是vector?
vector 是C++标准模板库(STL)中的一种容器,它本质上是一个可以自动调整大小的数组。你可以随意往里面添加或删除元素,它自己会管理内存空间,完全不用你操心“容量不够”的问题。和普通数组一样,它也可以通过下标快速访问元素(O(1)时间),但比数组灵活得多。
生活中的类比:
- 普通数组像固定大小的文具盒(只能装10支笔,多了放不下,少了空荡荡)
- vector像伸缩铅笔袋(可以塞进20支笔,也可以只放3支笔,袋子会贴合大小)
二、怎么创建一个vector?
1. 包含头文件
使用vector之前,必须在程序开头写:
#include <vector> // vector的头文件
2. 定义vector的几种常见方式
#include <vector>
using namespace std;
vector<int> scores; // 创建一个能装整数的空vector,名字叫scores
vector<double> heights; // 装小数的vector,名字叫heights
vector<string> names; // 装字符串的vector,名字叫names(需要#include <string>)
// 也可以提前指定大小(但后续还能继续增加)
vector<int> grades(30); // 创建一个vector,初始有30个元素,默认值都是0
vector<int> ages(10, 7); // 创建一个vector,初始有10个元素,每个元素都是7(比如10个小朋友都7岁)
// 还可以用花括号直接列出初始值(C++11开始支持)
vector<int> lucky_numbers = {1, 3, 7, 9, 15}; // 创建一个包含5个幸运数字的vector
创建空的vector就像拿了一个空的铅笔盒,准备往里装“铅笔”。
三、往里面装东西——push_back()
push_back() 方法在vector的末尾添加一个新元素。这是最常用的添加方式。
vector<int> scores; // 空vector
scores.push_back(90); // 装进第一个成绩90
scores.push_back(85); // 装进第二个成绩85
scores.push_back(100); // 装进第三个成绩100
// 现在scores里有3个元素:90, 85, 100
这个过程就像你往铅笔盒里一支一支地放铅笔,放进去的顺序就是它们在vector中的顺序。
除了push_back,还有pop_back():删除最后一个元素
scores.pop_back(); // 删除最后一个元素(100),现在scores只剩90和85
四、查看里面的东西——下标访问和at()方法
cout << scores[0] << endl; // 输出第一个元素:90
cout << scores.at(1) << endl; // 输出第二个元素:85
注意:下标从0开始,就像排队时第一个人的编号是0,第二个人的编号是1。
区别:
scores[i]:如果i超出了范围(比如访问scores[5]而vector只有3个元素),程序不会报错,而是返回一个垃圾值,非常危险。scores.at(i):如果i越界,程序会抛出一个异常并终止(在CSP-J中通常表现为程序崩溃)。所以推荐在不确定下标是否合法时用.at()。
五、知道有多少个元素——size()和empty()
cout << "一共有" << scores.size() << "个成绩" << endl; // 输出 2
if (scores.empty()) {
cout << "当前vector是空的" << endl;
} else {
cout << "当前vector不为空,有" << scores.size() << "个元素" << endl;
}
size() 返回当前元素个数(类型是 size_t,可以当作整数用)。
empty() 返回 true 如果vector是空的,否则返回 false。
六、遍历vector——找出所有元素
最传统的方式是用for循环配合下标:
for (int i = 0; i < scores.size(); i++) {
cout << scores[i] << " ";
}
从C++11开始,还可以用 范围for循环(也叫foreach),写起来更简洁:
for (int score : scores) { // 每次循环,score就依次等于scores里的每一个元素
cout << score << " ";
}
两种方法效果一样,但范围for循环不需要操心下标,也不怕写错边界。
七、新手容易犯的错误
错误1:忘记包含头文件
// 忘了 #include <vector>
vector<int> v; // 编译错误:vector未定义
正确做法:在文件开头加上 #include <vector>,并且加上 using namespace std; 或使用 std::vector。
错误2:用下标访问空vector
vector<int> v; // 空的
v[0] = 10; // 严重错误!v[0]不存在,程序可能崩溃或修改了不该碰的内存
正确做法:先添加元素,或者用 push_back 添加第一个元素,或者用 v.resize(1) 分配空间后再访问。
错误3:混淆 size() 和普通整数
size() 返回的是无符号整数 size_t,如果与一个有符号整数(比如 int)比较,编译器可能会给出警告。比较安全的写法是:
for (int i = 0; i < (int)scores.size(); i++) // 强制转换int
或者直接用 size_t i 循环。
错误4:不要用 [] 添加新元素
vector<int> v;
v[0] = 5; // 错误!v现在是空的,不能这样赋值
一定要用 push_back 或者先 resize 后再用 []。
八、完整示例:统计成绩并计算平均分
这个程序先让用户输入多个成绩(输入-1结束),然后显示所有成绩和平均分。
#include <iostream>
#include <vector> // vector头文件
using namespace std;
int main() {
vector<int> scores; // 空的vector,存放成绩
int score; // 临时变量,接收输入
cout << "请输入成绩(输入-1结束):" << endl;
while (true) {
cin >> score;
if (score == -1) {
break; // 结束输入
}
scores.push_back(score); // 把成绩放入vector
}
// 如果没有任何成绩,直接退出
if (scores.empty()) {
cout << "没有输入任何成绩。" << endl;
return 0;
}
// 输出所有成绩
cout << "你一共输入了 " << scores.size() << " 个成绩:";
for (int s : scores) { // 范围for循环,s依次取每个成绩
cout << s << " ";
}
cout << endl;
// 计算总和
int sum = 0;
for (int s : scores) {
sum += s;
}
double average = (double)sum / scores.size(); // 注意:把其中一个转为double
cout << "平均分:" << average << endl;
return 0;
}
运行示例:
请输入成绩(输入-1结束):
95
88
76
100
-1
你一共输入了 4 个成绩:95 88 76 100
平均分:89.75
九、常用其他操作一览(供查阅)
| 操作 | 作用 | 示例 |
|---|---|---|
v.clear() | 清空所有元素(变成空vector) | scores.clear(); |
v.pop_back() | 删除最后一个元素 | scores.pop_back(); |
v.insert(pos, value) | 在位置pos前插入一个元素 | scores.insert(scores.begin()+1, 90); |
v.erase(pos) | 删除位置pos处的元素 | scores.erase(scores.begin()); |
v.resize(n) | 重新设置大小为n,多出的元素用默认值填充 | scores.resize(10); |
v.front() | 返回第一个元素 | int first = scores.front(); |
v.back() | 返回最后一个元素 | int last = scores.back(); |
注意:insert 和 erase 会引起元素的移动,效率较低(O(n)),大量插入删除不如使用 list。
十、小练习(动手试试)
-
创建一个
vector<string>存放你的三个好朋友的名字(用push_back添加),然后使用范围for循环输出每个名字。别忘了包含<string>头文件哦! -
创建一个
vector<int>存放1到10的整数(用for循环push_back),然后删除最后一个数,再输出剩下所有数的和。 -
挑战题:从键盘读入5个价格(double类型),存入vector,然后找出最高价和最低价。
十一、相关指引
vector是STL中最常用的序列容器。学完vector后,你还可以学习:
algorithm头文件:配合vector使用排序、查找等算法(比如sort(v.begin(), v.end())可以把成绩从小到大排序)list双向链表:如果需要在中间频繁插入或删除元素,用list比vector更高效stack和queue:基于vector或deque实现的栈和队列,适合“后进先出”或“先进先出”的场景map映射表:像字典一样存储键值对,例如把学生姓名映射到他的成绩
掌握了vector,你就掌握了C++中最实用、最灵活的数据容器之一!快去试试用vector解决你作业里的数据存储问题吧。
例题精讲
下列关于C++中vector动态数组的描述,哪一项是正确的?
在C++中,使用vector<int> v;声明一个空的vector后,立即执行cout << v[0];不会导致程序运行错误。
以下代码使用vector存储整数并输出所有元素,请补全缺失的部分。
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
for(int i=0; i<5; i++) {
___; // 将i的平方添加到vector末尾
}
for(int i=0; i<v.size(); i++) {
cout << ___ << " "; // 输出第i个元素
}
return 0;
}关于vector的迭代器,以下说法正确的是?
使用reserve()可以改变vector的size,使元素个数增加。