<C++ STL> Vector

目录

一、构造函数

二、空间问题

1. reserve与resize

三、vector增删查改

四、如何扩容

五、例题

六、算法

sort


前言 

     学习完string,我们再来看vector(向量)——可变大小数组的序列容器,其实本质就是顺序表,可以是任意类型,如char、int、string、vector等等。

        本节学习vector的常用接口。 


标准库中的vector类

        alloctor是内存池,C++为了提高内存申请效率而设计的,有缺省值,如果对C++的设计不满意,可以自己传参修改


一、构造函数

构造函数声明接口说明
vector()(重点)无参构造
vector (size_type n, const value_type& val = value_type())构造并初始化n个val
vector (const vector& x)((重点)拷贝构造
vector (Inputlterator first, Inputlterator last)使用迭代器进行初始化构造
    vector<int> v1(10, 1);
    //例一:
	vector<string> v2(10, "***");

	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	for (auto e : v2)
	{
		cout << e << " ";
	}
	cout << endl;

	// 自己类型的迭代器
	vector<int> v3(v1.begin(), v1.end());
	for (auto e : v3)
	{
		cout << e << " ";
	}
	cout << endl;
    
    //例四:
	string str("hello world");
	vector<char> v4(str.begin(), str.end());
	for (auto e : v4)
	{
		cout << e << " ";
	}
	cout << endl;
    
    //例五:
	int a[] = { 16,2,77,29 };
	vector<int> v5(a, a+4);
	for (auto e : v5)
	{
		cout << e << " ";
	}
	cout << endl;

二、空间问题

容量空间接口说明
size获取数据个数
capacity获取容量大小
empty判断是否为空
resize改变vector的size和capacity
reserve改变vector的capacity

 

reserve && resize

        预留容量空间,是为了提高扩容效率,避免多次扩容空间。

我们来看下面一段代码:

vector<int> v;
v.reserve(10);

for (size_t i = 0; i < 10; i ++ )
{
    v[i] = i;
}

        运行后发现越界,这是错误写法,因为[ ] 重载函数内会判断i是否小于size,是以size为标准的,所以不能插入到size与capacity之间的空间中 

        所以,如果想访问这之间的空间,我们需要使用resize函数,将size与capacity同时更新

​vector<int> v;
v.resize(10);

for (size_t i = 0; i < 10; i ++ )
{
    v[i] = i;
}

​

三、vector增删查改

vector增删查改接口说明
push_back尾插
pop_back尾删
find查找(在算法模块,不是vector的成员接口)

insert

在pos之前插入val
erase删除pos位置的数据
swap交换两个vector的数据空间
operator[ ]像数组一样访问

 

举例: 

	int a[] = { 16,2,77,29,3,33,43,3,2,3,3,2 };
	vector<int> v1(a, a + sizeof(a)/sizeof(int));
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	// 头删
	v1.erase(v1.begin());
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	// 头插 
	v1.insert(v1.begin(), 100);
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	// 删除第3个数据
	v1.erase(v1.begin()+2);
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	// 删除3,但是不知道3在哪个位置,怎么办?
	//vector<int>::iterator pos = find(v1.begin(), v1.end(), 3);
	auto pos = find(v1.begin(), v1.end(), 3);
	/*if (pos != v1.end())
	{
		v1.erase(pos);
	}*/

 如果要删除所有值为x的元素,要怎么做呢? 

        如果将上面的代码使用循环,每次再从pos + 1处find,最后会涉及迭代器失效问题,出现错误。这个问题,我们后面再来解决。

	// 删除所有的3 -- 涉及迭代器失效!后面解决
	while(pos != v1.end())
	{
		v1.erase(pos);
		//pos = find(pos+1, v1.end(), 3);
		pos = find(v1.begin(), v1.end(), 3);
	}

四、如何扩容

我们来看在vs和Linus中扩容情况:

void TestVectorExpand()
{
	size_t sz;
	vector<int> v;
	sz = v.capacity();
	cout << "making v grow:\n";
	for (int i = 0; i < 100; ++i)
	{
		v.push_back(i);
		if (sz != v.capacity())
		{
			sz = v.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

         大致为1.5倍扩容,而在Linus上,为2倍扩容

五、例题

如何理解 vector<vector<int>>  ?

        我们可以分析vector<int> 

        

        数组a的类型是int* ,a数组内的每个元素类型是int

        那么类比来看vector<vector<int>> 

        此时数组a的类型变为 vector<int> *,是一个vector的指针类型(是一个对象数组),数组内的每个元素类型是vector<int> ,每个元素都有各自的数组a、siza、capacity。

        所以,vector<vector<int>> 就是二维数组,数组的长度可以不一致。

        对于二维的vector,可以使用v[ i ][ j ]来访问数据,它的原理是:第一个v[ i ]表示v.operator[]( i ),返回的值类型是vector<int>&,而第二个[ ],表示的是v[ i ].operator[]( j ),返回的值类型是int。

学习了vector的使用,我们来做一个例题,充分使用vector

例题1:

https://leetcode.cn/problems/letter-combinations-of-a-phone-number/description/

class Solution {
public:
    string a[10] = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

public:
    //多路递归
    void Combinations(const string& digits, int level, string str, vector<string>& v)
    {
        if (level == digits.size())
        {
            v.push_back(str);
            return;
        }

        //取每一层对应映射的字母
        int num = digits[level] - '0';
        string tmp(a[num]);
        for (int i = 0; i < tmp.size(); ++ i)
        {
            //注意:我们没有改变str的值,不是+=,我们只是在或面加了一个字母
            //所以递归回溯后,不需要还原
            Combinations(digits, level + 1, str + tmp[i], v);
        }
        
    }

    //全排列
    vector<string> letterCombinations(string digits) 
    {
        vector<string> res;
        if (digits.size() == 0)
            return res;

        Combinations(digits, 0, "", res);

        return res;
    }

};

       具体理解,可以自己画递归展开图

六、算法

1. sort

  • 参数传迭代器 (string、vector等都可使用 sort 进行排序)
  • 默认升序,如果想排为降序,使用仿函数匿名对象即可
  • 实现的算法 :快排
	int a[] = { 16,2,77,29 };
	vector<int> v5(a, a+4);
	for (auto e : v5)
	{
		cout << e << " ";
	}
	cout << endl;

	// 升序 < 
	// less
	sort(v5.begin(), v5.end());
	//sort(v5.rbegin(), v5.rend());
	for (auto e : v5)
	{
		cout << e << " ";
	}
	cout << endl;
	// 降序 >
	//greater<int> gt;
	//sort(v5.begin(), v5.end(), gt);

    //greater<int>() 匿名对象
	sort(v5.begin(), v5.end(), greater<int>());
	for (auto e : v5)
	{
		cout << e << " ";
	}
	cout << endl;

 总结


        本节初步了解vector类的使用方法,具体更多的接口概念与定义在网站内查询。

vector - C++ Reference (cplusplus.com)

        下节课,我们将模拟实现vector

        最后,如果小帅的本文哪里有错误,还请大家指出,请在评论区留言(ps:抱大佬的腿),新手创作,实属不易,如果满意,还请给个免费的赞,三连也不是不可以(流口水幻想)嘿!那我们下期再见喽,拜拜!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值