在C++中,vector是一个非常有用的“容器”,它能够存放各类型的数据,并且可以动态分配内存。下面介绍一下使用vector需注意的几点:
1.vector数组的初始化
(1): vector ilist1;
默认初始化,vector为空, size为0,表明容器中没有元素,而且 capacity 也返回 0,意味着还没有分配内存空间。这种初始化方式适用于元素个数未知,需要在程序中动态添加的情况。
(2): vector ilist = {1,2,3.0,4,5,6,7};
这种初始化类似于普通数组的初始化形式
ilist 初始化为列表中元素的拷贝,列表中元素必须与ilist的元素类型相容,本例中必须是与整数类型相容的类型,整形会直接拷贝,其他类型会进行类型转换
(3): vector ilist(5);
默认值初始化,ilist中将包含5个元素,每个元素进行缺省的值初始化,对于int,也就是被赋值为0,因此ilist被初始化为包含5个0。当程序运行初期元素大致数量可预知,而元素的值需要动态获取的时候,可采用这种初始化方式。
(4):vector ilist(7,3);
指定值初始化,ilist被初始化为包含7个值为3的int
常见错误赋值方法
**vector<int>a;
for(int i=0;i<10;++i){a[i]=i;}//下标只能用来获取已经存在的元素**
2、Vector作为函数的参数或者返回值时,需要注意它的写法:
double Distance(vector&a, vector&b) 其中的“&”一定不能少!!!
下面是以vector作为返回值时的写法
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int rob(TreeNode* root) {
vector<int>res=dp(root);
return max(res[0],res[1]);
}
vector<int> dp(TreeNode* root){
if(root==NULL)
return vector<int>{0,0};
vector<int>left=dp(root->left);
vector<int>right=dp(root->right);
int rob=root->val+left[0]+right[0];
int not_rob=max(left[0],left[1])+max(right[0],right[1]);
return vector<int>{not_rob,rob};//注意此处not_rob与rob的位置
//因为我们定义的是arr[0]是不抢,arr[1]代表抢,所以第一个元素必须是
//not_rob,否则会得到错误的答案。
}
};
vector的元素不仅仅可以是int,double,string,还可以是结构体,但是要注意:结构体要定义为全局的,否则会出错。
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<iostream>
using namespace std;
typedef struct rect
{
int id;
int length;
int width;
//对于向量元素是结构体的,可在结构体内部定义比较函数,下面按照id,length,width升序排序。
bool operator< (const rect &a) const
{
if(id!=a.id)
return id<a.id;
else
{
if(length!=a.length)
return length<a.length;
else
return width<a.width;
}
}
}Rect;
int main()
{
vector<Rect> vec;
Rect rect;
rect.id=1;
rect.length=2;
rect.width=3;
vec.push_back(rect);
vector<Rect>::iterator it=vec.begin();
cout<<(*it).id<<' '<<(*it).length<<' '<<(*it).width<<endl;
return 0;
}
vector是线性容器,它的元素严格的按照线性序列排序,和动态数组很相似,和数组一样,它的元素存储在一块连续的存储空间中,这也意味着我们不仅可以使用迭代器(iterator)访问元素,还可以使用指针的偏移方式访问,和常规数组不一样的是,vector能够自动存储元素,可以自动增长或缩小存储空间,
vector的优点:
-
可以使用下标访问个别的元素
-
迭代器可以按照不同的方式遍历容器
-
可以在容器的末尾增加或删除元素
和数组相比,虽然容器在自动处理容量的大小时会消耗更多的内存,但是容器能提供和数组一样的性能,而且能很好的调整存储空间大小
和其他标准的顺序容器相比(deques or lists),能更有效访问容器内的元素和在末尾添加和删除元素,在其他位置添加和删除元素,vector则不及其他顺序容器,在迭代器和引用也不比lists支持的好。
如果你要表示的向量长度较长(需要为向量内部保存很多数),容易导致内存泄漏,而且效率会很低。
二维数组初始化
std::vector vec(10,90); //将10个一维动态数组初始为90
std::vector<std::vector > vec(row,vector(col,0)); //初始化row * col二维动态数组,初始化值为0,其实就是每一行初始化为列数个0
int size_row = vec.size(); //获取行数
int size_col = vec[0].size(); //获取列数
下面是leetcode上“二叉树的层次遍历”问题的代码,其中很好地运用了二维动态数组来解决问题,思路简洁明了。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>>ans;
pre(root,0,ans);
return ans;
}
void pre(TreeNode *root,int depth,vector<vector<int>>&ans){
if(!root) return;
if(depth>=ans.size()){
//二维数组每行存储一层的数据,到下一层遍历时,depth加一
//所以当depth>=行数时,证明到了下一层的遍历,需要追加一行
ans.push_back(vector<int>{});
}
ans[depth].push_back(root->val);
pre(root->left,depth+1,ans);
pre(root->right,depth+1,ans);
}
};
而为数组追加行数时,直接用数组名.push_back(vector<>{}//注意此时的{}不能省去)而在某一行追加列数时,用数组名[行数].push_back();