• 【STL】vector


    1. vector

    vector中文意思是向量,它是一个可以改变大小的动态顺序表。
    在这里插入图片描述

    2. vector常用接口

    2.1 构造函数

    constructor接口说明
    vector()(重点)无参构造
    vector (const vector& x); (重点)拷贝构造
    vector(size_type n, const value_type& val = value_type())构造并初始化n个val
    vector (InputIterator first, InputIterator last);使用迭代器进行初始化构造

    vector是一个类模板,它不仅可以存储int、double等类型,还可以存储string,严格来说vector可以存储任意类型。

    void test_vector1()
    {
    	vector<int> v1;
    	v1.push_back(1);
    	v1.push_back(2);
    	v1.push_back(3);
    	v1.push_back(4);
    
    	vector<double> v2;
    	v2.push_back(1.1);
    	v2.push_back(2.2);
    	v2.push_back(3.3);
    
    	vector<string> v3;
    	//单参数的构造函数支持隐式转换
    	//string(const char* str)
    	//string s = "hello world";
    	//常量字符串构造一个临时对象
    	//再拷贝构造给s
    	//被优化成直接构造s
    	v3.push_back("李白");
    	v3.push_back("杜甫");
    	v3.push_back("苏轼");
    	v3.push_back("白居易");
    	
    	//10个5初始化
    	vector<int> v4(10, 5);
    	
    	//迭代器区间初始化
    	vector<string> v5(++v3.begin(), --v3.end());
    	string s = "hello world";
    	vector<char> v6(s.begin(), s.end());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    测试:
    在这里插入图片描述

    2.2 遍历

    void test_vector2()
    {
    	// 遍历
    	vector<int> v;
    	v.push_back(1);
    	v.push_back(2);
    	v.push_back(3);
    	v.push_back(4);
    
    	// 1、下标+[]
    	for (size_t i = 0; i < v.size(); ++i)
    	{
    		v[i] += 1;
    		cout << v[i] << " ";
    	}
    	cout << endl;
    
    	// 2.迭代器
    	vector<int>::iterator it = v.begin();
    	while (it != v.end())
    	{
    		*it -= 1;
    		cout << *it << " ";
    		++it;
    	}
    	cout << endl;
    
    	// 3.范围for
    	for (auto e : v)
    	{
    		cout << e << " ";
    	}
    	cout << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    测试:
    在这里插入图片描述

    2.3 增容

    void test_vector3()
    {
    	size_t sz;
    	vector<int> foo;
    
    	//当前容量
    	sz = foo.capacity();
    	//增容,容量变了就打印一下
    	cout << "making foo grow:\n";
    	for (int i = 0; i < 100; ++i) 
    	{
    		foo.push_back(i);
    		if (sz != foo.capacity()) 
    		{
    			sz = foo.capacity();
    			cout << "capacity changed: " << sz << '\n';
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    vs2019下测试:vs(PJ版本STL)下大概是1.5倍的增容
    在这里插入图片描述
    Linux下:g++(SGI版本STL)是按2倍增长的

    g++运行结果:
    making foo grow:
    capacity changed: 1
    capacity changed: 2
    capacity changed: 4
    capacity changed: 8
    capacity changed: 16
    capacity changed: 32
    capacity changed: 64
    capacity changed: 128
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    单词增容增多少的分析:
    单次增容越多,插入N个值,增容次数越少,效率就越高。
    单次增容越多,可能浪费就越多。
    单次增少了,会导致频繁增容,效率低下,

    所以VS、Linux分别选择1.5倍和2倍增容,这也是平衡过的结果。

    如果我们已经知道要使用多大的空间,就可以用reserve提前把空间开好(resize会改变size,插入还是会扩容):
    在这里插入图片描述

    2.4 shrink_to_fit

    string、vector都有一个特点:删除数据,一般是不会主动缩容。vector提供shrink_to_fit来请求容器减少容量以适应其大小。
    shrink_to_fit的缺点:
    (1)如果之后又要插入数据,就又要扩容,那还缩容干嘛!
    (2)操作系统不允许内存还一部分,所以缩容的实际操作是先申请一块缩容大小(假设为n个字节)的空间,再把原空间的前n个字节拷贝过来,再释放原空间。

    shrink_to_fit付出了性能代价,建议大家慎用。

    void test_vector4()
    {
    	size_t sz;
    	vector<int> foo;
    	foo.reserve(100);
    	foo.resize(10);
    
    	cout << foo.size() << endl;
    	cout << foo.capacity() << endl;
    
    	// 慎用、少用
    	foo.shrink_to_fit();
    	cout << foo.size() << endl;
    	cout << foo.capacity() << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    测试:
    在这里插入图片描述

    2.5 insert和erase

    vector的insert不支持下标,只支持迭代器。

    void test_vector5()
    {
    	// 遍历
    	vector<int> v;
    	v.push_back(1);
    	v.push_back(2);
    	v.push_back(3);
    	v.push_back(4);
    
    	v.insert(v.begin(), -1);
    	v.insert(v.begin(), -2);
    	v.insert(v.begin(), -3);
    
    	for (auto e : v)
    	{
    		cout << e << " ";
    	}
    	cout << endl;
    
    	v.insert(v.begin()+7, 300);
    	//v.insert(v.begin()+8, 300);越界,非法的迭代器位置
    
    	for (auto e : v)
    	{
    		cout << e << " ";
    	}
    	cout << endl;
    	v.erase(v.begin());
    	v.erase(v.begin());
    
    	for (auto e : v)
    	{
    		cout << e << " ";
    	}
    	cout << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    在这里插入图片描述

    2.6 find

    vector没有查找函数,但是可以复用algorithm库里的find。
    在这里插入图片描述

    void test_vector6()
    {
    	// 遍历
    	vector<int> v;
    	v.push_back(1);
    	v.push_back(2);
    	v.push_back(3);
    	v.push_back(4);
    
    	//vector<int>::iterator pos = find(v.begin(), v.end(), 3);
    	auto pos = find(v.begin(), v.end(), 3);
    	if (pos != v.end())
    	{
    		cout << "找到了" << endl;
    		v.erase(pos);
    	}
    	else
    	{
    		cout << "没有找到" << endl;
    	}
    
    	for (auto e : v)
    	{
    		cout << e << " ";
    	}
    	cout << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    在这里插入图片描述

    2.7 sort

    在这里插入图片描述

    void test_vector7()
    {
    	vector<int> v;
    	v.push_back(1);
    	v.push_back(2);
    	v.push_back(3);
    	v.push_back(4);
    	v.push_back(0);
    	v.push_back(9);
    	v.push_back(3);
    	v.push_back(1);
    
    	// 默认是升序
    	sort(v.begin(), v.end());
    	for (auto e : v)
    	{
    		cout << e << " ";
    	}
    	cout << endl;
    
    	// 排降序,仿函数
    	// 关于仿函数,大家先记住这个用法,具体我们后面讲队列再详细讲
    	sort(v.begin(), v.end(), greater<int>());  // >
    	for (auto e : v)
    	{
    		cout << e << " ";
    	}
    	cout << endl;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在这里插入图片描述

    3. 练习题

    3.1 杨辉三角

    杨辉三角
    在这里插入图片描述
    关于题目给的vector(vector<int>):
    在这里插入图片描述
    核心思想:找出杨辉三角的规律,发现每一行头尾都是1,中间第[j]个数等于上一行[j-1]+
    [j]

    class Solution {
    public:
        vector<vector<int>> generate(int numRows) {
        vector<vector<int>> vv;
        // 先开辟杨辉三角的空间
        vv.resize(numRows);
        //初始化每一行
        for(size_t i = 0; i < numRows; ++i)
        {
            //每行个数依次递增
            vv[i].resize(i+1, 0);
            // 每一行的第一个和最后一个都是1
            vv[i][0] = 1;
            vv[i][vv[i].size()-1] = 1;
        }
        for(size_t i = 0; i < vv.size(); ++i)
        {
            for(size_t j = 0; j < vv[i].size(); ++j)
            {
                if(vv[i][j] == 0)
                {
                    //之间位置等于上一行j-1和j个相加
                    vv[i][j] = vv[i-1][j-1] + vv[i-1][j];
                }
            }
        }
        return vv;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    C语言参考代码:
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    关于安卓12闪屏页适配(一)
    在使用VSCode软件编写代码时,突然字符之间间隔变大了-----已解决
    Selenium隐藏浏览器和元素截屏实践
    高数 |【2020数一真题】部分错题及经典题自用思路整理
    ImportError: cannot import name ‘Config‘ from ‘mmcv‘ 问题解决
    Git基本使用教程(学习记录)
    如何把Android Framework学彻底?一条龙学习
    基于Python3.6配置开发环境
    运行django
    我悟了!Mysql事务隔离级别其实是这样!
  • 原文地址:https://blog.csdn.net/iwkxi/article/details/125612605