【C++】vector创建数组相关知识点总结

种一棵树最好的时间是十年前,其次是现在。

文章目录

一、一维数组

1、创建

2、添加元素、赋值

3、删除元素

4、长度相关

5、是否空&清空

6、排序&翻转&合并

7、vector数据类型可以自定义

二、二维数组

1、初始化

2、添加元素

3、长度获取

4、赋值

5、输出

6、遍历&迭代器赋值

7、删除(乏了乏了,直接复制别人写的)

三、出现的问题

前言

在C++创建数组时需要提前分配好大小,但是vector可以解决这个问题,大小用nums.size()表示即可。使用起来特别简便。我对学到的一维数组和二维数组的相关知识点做了总结,还有几道题目(为了避免篇幅太长,放在下一篇里单独说)。

头文件:#include<vector>,而且要加using namespace std;

一、一维数组

1、创建

    vector<int>nums;//创建整型一维数组
    vector<int>nums(n);//指定长度为n
    vector<int>nums(5,3);//创建[3 3 3 3 3]

2、添加元素、赋值

    nums.push_back(a);//在数组末尾添加a
    num[i]=2;//直接赋值
    vector<int>nums1;
    nums1=nums;//可以整体赋值

3、删除元素

    nums.resize(nums.size()-i);//减少i个元素
    nums.pop_back();//括号里面不用加东西,删除最后一个元素

4、长度相关

    nums.size();//数组的长度
    cout << nums[0] << endl;//输出第一个元素
    cout << nums[nums.size()-1] << endl;//输出最后一个元素
    nums.resize(m);//长度改为m

5、是否空&清空

    nums.empty() //判断是否空
    nums.clear() //清空

6、排序&翻转&合并

#include<algothrim>
    
    sort(nums.begin(),nums.end());//从小到大排序
    sort(nums.begin(),nums.begin()+3);//排序前面三个数

    reverse(nums.begin(),nums.end());//翻转
    
    //将nums1和nums2合并
    vector<int>nums1(m),nums2(n);
    vector<int>nums;
    nums.resize(m+n);
    merge(nums1.begin(),nums1.end(),nums2.begin(),nums2.end(),nums);

7、vector数据类型可以自定义

struct Stu{
    string name;
    int score;
};
int main()
{
    vector<Stu>vec;

    //创建a再赋值
    Stu a;
    a.name="abc";
    a.score=100;
    vec.push_back(a);

    //直接赋值
    vec.push_back({"acb",90});
}

二、二维数组

1、初始化

方法一:创建&直接初始化

    vector<vector<int>>nums;//创建数组
    vector<vector<int> >nums;//有人说必须打空格,但是我不打空格好像也没事
    
    vector<vector<int>>nums(3);//创建三行的数组
    vector<vector<int>>nums(3,vector<int>(5,0)); //创建三行五列的数组,初始值为0

方法二:用resize构建

下面定义的是行为r(row),列为c(column)的二维数组,初始值为0(因为resize默认为0)。

    vector<vector<int>> new_mat(r);//注意这个r是不可缺少的,规定其有多少行
    for(int i=0 ;i<r; i++) //二维vector的初始化时有要求的
    {
         new_mat[i].resize(c);
    }

2、添加元素

场景1:插入的是一个数组

    vector<vector<int>>A;
    vector<int>B;
    B.push_back(0);
    B.push_back(1);
    A.push_back(B);

    B.clear();
    B.push_back(3);
    B.push_back(4);
    A.push_back(B);

场景2:每行不一定几个数,就是想对每行的列进行操作,且插入的是元素

每一行的元素个数可以不相同!!!在声明时,行数一定要有!!然后push_back就可以了!

    vector<vector<int>>mat(r);//每行的定义
    mat[i].push_back(1);//这就是该第i-1行的插入一个元素,值为1

别人写的杨辉三角:

    vector<vector<int>> generate(int numRows) {
        vector<vector<int>>mat(numRows);
        vector<int> tem;
        tem.reserve(1000);
        for(int i=0;i<numRows;i++)
        {
            for(int j=0;j<i+1;j++)
            {
                if((j==0)||(j==i))mat[i].push_back(1);
                else
                {
                    int value = tem[j-1]+tem[j];
                    mat[i].push_back(value);
                }
            }
            tem.clear();//一维数组只清除里面的元素,而不对容量做操作。
            for(auto it=mat[i].begin();it!=mat[i].end();it++)
            {
                tem.push_back(*it);
            }
        }

3、长度获取

    m=A.size();//row
    n=A[0].size();//column

4、赋值

    A[0][0]=4;
    A.push_back({ 1,1 });//这样[1,1]就进入A数组了

5、输出

    auto it = a.begin();
    a.erase(++it);//删除第一行
    auto it2 = it.begin();
    a[0].erase(++it2);//删除第一行的第一列,注意0不要忘记

其中,it2也可直接定义,而不去依靠it。

    for(auto it2=mat[i].begin();it2!=mat[i].end();it2++)
     {
      tem.push_back(*it2);
     }

6、遍历&迭代器赋值

    //遍历	
    for (auto it = new_mat.begin(); it != new_mat.end(); it++)
	{
		for (auto it2 = it->begin(); it2 != it->end(); it2++)
		{
			cout << "[" <<  *it2 << "]";
		}
		cout << endl;
	}


    //迭代器赋值
    for(auto it=ans.begin();it!=ans.end();it++)
    {
       if(key == (*it)[0])  (*it)[1]=value;//注意括号是要把整个*it括起来的!
    }

7、删除(乏了乏了,直接复制别人写的)

首先先说本方法,用STL成员函数的,例如删除2

 for(auto it=ans.begin();it!=ans.end();it++)
    {
        if((*it)[0] == 2) it = ans.erase(it);//注意erase里面是要放迭代器的
        if(it == ans.end()) break;//这一步是要防止当删除的元素为最后一个,导致it++直接爆炸
    }

可以看到,上面又是必须迭代器,又是要加一步检查,那如何更好地快速处理呢?以一维为例!!(erase和remove结合即可):

ans.erase(remove(ans.begin(), ans.end(), 2), ans.end());

remove是algorithm库中地函数,并不是真正地删除,而是以覆盖的方式将满足删除条件的元素移到容器最后(其实就是想调用函数找到迭代器)。然后我们删除erase最后的元素即可快速删除。那么对于二维来说呢(例如我要删除二维中第一个元素为2的数组)可以看到,并不简单。

for(auto it=ans.begin();it!=ans.end();it++)
{
   if(key == (*it)[0]) ans.erase(std::remove(ans.begin(),ans.end(),*it),ans.end());
   if(it == ans.end()) break;
}    

三、出现的问题

使用动态数组时会产生问题:(虽然我也没遇到过,不过记录下来万一用到了嘞)

1、在处理小数据时是没问题的,但处理大数据时,vector在重新分配发生时一般会把容量(所分配好的内存空间)翻倍,这将导致出现大量的冗余空间。

2、在对二维数组创建时,会出现创建失败的情况,如下就会报错:

    vector<vector<int>>nums;
    nums[0].push_back(1);
    cout << nums[0][0];

首先要明白,我们第二个问题的出现,其实就是因为第一个问题,那么我们逐个分析一下:
对vector的.size()代表时查找里面有多少个数,而.capacity()是查询他的容量(最多放多少个数)。因此我们有两个方法来解决:
1、resize(Container::size_type n)强制把容器改为容纳n个元素。调用resize之后,size将会返回n。如果n小于当前大小,容器尾部的元素会被销毁。如果n大于当前大小,新默认构造的元素会添加到容器尾部。如果n大于当前容量,在元素加入之前会发生重新分配。
2、reserve(Container::size_type n)强制容器把它的容量改为至少n,提供的n不小于当前大小。这一般强迫进行一次重新分配,因为容量需要增加。(如果n小于当前容量,vector忽略它,这个调用什么都不做,string可能把它的容量减少为size()和n中大的数,但string的大小没有改变。


【小结】上述两方法的区别
1、reserve表示容器预留空间,但并不是真正的创建对象,需要通过insert()或push_back()等创建对象。resize既分配了空间,也创建了对象。
2、reserve只修改capacity大小,不修改size大小,resize既修改capacity大小,也修改size大小。
3、resize带两个参数,一个表示容器大小,一个表示初始值(默认为0)。reserve只带一个参数,表示容器预留的大小。
因此,我们在对一维数组push前,可以来一个reverse,这样在不断push的过程中就不会发生重新分配了。如:vector<int> a; a.reserve(1000);

阐述一下第二个问题出现的原因:vector直接根据下标访问必须要先push,存在数才行。而上面想直接对第一行里面的各个元素进行访问修改时绝对不行的。但是相反,如果我们先对第一行进行赋值,然后再访问,这样又是可以的,如:

    vector<vector<int>> a;
    vector<int> b;
    b.push_back(1);
    a.push_back(b);//相当于增加二维数组中的行
    cout << a[0][0];

第一次写博客,若有错误欢迎指正,如果有版权问题请及时与我联系修改删除,感谢感谢!!!

参考的博主:

1、https://blog.csdn.net/jackywgw/article/details/6248342
2、https://blog.csdn.net/liuweiyuxiang/article/details/88692708
3、https://blog.csdn.net/qq_38289815/article/details/106052582
4、https://blog.csdn.net/qq_31918961/article/details/90109988
5、https://blog.csdn.net/m0_57298796/article/details/123952640

  • 10
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值