我们先回顾一下数组是什么,它其实是存在内存中的,且全局和局部数组存储的位置不一样。
我们会发现,数组会带来两个限制,一是数组在定义时就要指定大小(一个常量)且这个大小不能改变,二是在函数内部定义的数组不能太长,因为它是存储在空间较小的栈上,不能超出限制。
因此,我们可以使用C++风格的一个容器即向量vector,是一个动态数组,它是顺序存储的线性表。
下面是关于vector的一些常用操作。
//向量vector
#include <vector>
#include <cstdio>
using namespace std;
int main(){
vector<int> vec1;
//尾部扩容
vec1.push_back(1);
vec1.push_back(3);
//让一开始就有元素
vector<int> vec2 {1,2,3};
//随机位置插入和删除元素
vector<int>::iterator it1 = vec2.begin() + 1;//迭代器指向第二个位置
vec2.insert(it1,4);//第二个位置之前插入元素4,即 1,4,2,3
vec2.erase(vec2.begin());//删除第一个位置元素,即 4,2,3
//遍历元素
for (unsigned i = 0; i < vec2.size(); ++i) {
printf("vec2[%d] = %d\n", i, vec2[i]);
}
// //使用迭代器遍历
// for(vector<int>::iterator it = vec2.begin(); it != vec2.end(); ++it){
// printf("vec2[] = %d\n", *it);
// }
// //结果
// vec2[0] = 4
// vec2[1] = 2
// vec2[2] = 3
//弹末尾元素
vec2.pop_back();
vec2.pop_back();
//int arr[10000];
vector<int> vec3(10000);// [0]~[9999] 元素都是0
}
vector的begin()和end()与map的相似,注意insert是把元素插在迭代器指向位置之前。
例题1 完数与盈数 (清华大学复试上机题)
题目描述:
一个数如果恰好等于它的各因子(该数本身除外)子和,如:6=3+2+1。则称其为“完数”;若因子之和大于该数,则称其为“盈数”。 求出2到60之间所有“完数”和“盈数”。
输入描述:
题目没有任何输入。
输出描述:
输出2到60之间所有“完数”和“盈数”,并以如下形式输出: E: e1 e2 e3 ......(ei为完数) G: g1 g2 g3 ......(gi为盈数) 其中两个数之间要有空格,行尾不加空格。
代码示例:
//完数和盈数
#include <cstdio>
#include <vector>
using namespace std;
//约数和
int Sum(int i){
int sum = 0;
for (int j = 1; j < i; ++j) {
if(i%j==0){
sum = sum + j;
}
}
return sum;
}
int main(){
vector<int> Evec;//完数 28=1+2+4+7+14
vector<int> Gvec;//盈数
for (int i = 2; i <= 60; ++i) {
if(i == Sum(i)){
Evec.push_back(i);
}
else if(i < Sum(i)){
Gvec.push_back(i);
}
}
printf("E:");
for (unsigned i = 0; i < Evec.size(); ++i) {
printf(" %d",Evec[i]);
}
printf("\n");
printf("G:");
for (unsigned i = 0; i < Gvec.size(); ++i) {
printf(" %d",Gvec[i]);
}
printf("\n");
}
分析:
可以发现要找2-60内的完数与盈数,可以使用枚举的方法,而每次找到的数要放到数组中,这是一个动态的过程,显然用vector十分有用,每次进行push_back。
一个数的约数一定比该数小,因此我们可以把小于该数的数都进行求余操作,无余数即为约数,最后再将这些约数求和即可,这一过程可以用一个自定义函数实现。
以下补充为vector在内存中的存储方式,它的扩容机制优秀,打破了普通数组的限制。