【C++】—— vector使用

简介: 【C++】—— vector使用

前言

1. vector是表示可变大小数组的序列容器。
2. vector就像数组一样,也采用连续的存储空间来存储元素。这样我们就可以采用下标来访问vector的元素;但vector又不是数组,它的大小是动态可变的,会被容器自动处理。
3. 与其他动态序列的容器(比如list、deque等),vector访问元素更加高效,在末尾添加/删除元素更加高效(尾删、尾插);对于不在尾部删除或插入数据操作,效率就低一些。
4. STL库里面vector是一个类模版,使用时需要实例化。(比如: vector<int>)

vector构造函数

STL库里面构造函数参数有空间适配器(allocator),这里先不了解这一方面的内容(后面再详细学习)。

(constructor)构造函数 接口说明
vector (); (重点) 无参构造(默认构造)
vector(size_type n, const value_type& val = value_type()) 构造并初始化成n个val
vector (InputIterator first, InputIterator last); 使用迭代器进行初始化构造
vector (const vector& x); (重点) 拷贝构造
void test1()
{
  vector<int> v1; //无参构造(默认构造)
  vector<int> v2(10, 1); //构造初始化并初始化成10个1
  vector<int> v3(v2.begin(), v2.end()); //使用迭代器区间初始化
  vector<int> v4(v2); //拷贝构造
}

vector迭代器

在string和vector中迭代器并没有广泛使用(可以进行下标访问);但是任何容器中都可以使用迭代器来遍历,通用性比较强。

iterator的使用 接口说明
begin() 和 end() (重点) begin()获取第一个位置的iterator/const_iterator、end()获取最后一个位置的iterator/const_iterator
rbegin() 和 rend() (反向迭代器) rbegin()获取最后一个位置的iterator/const_iterator、rend()获取第一个的iterator/const_iterator

有了迭代器,我们还可以使用范围for这一个语法糖。

这里为了方便观察,就先使用**push_back()**尾插一些数据。

void test2()
{
  vector<int> v1;
  v1.push_back(1);
  v1.push_back(2);
  v1.push_back(3);
  v1.push_back(4);
  v1.push_back(5);
  //正向迭代器
  std::vector<int>::iterator it = v1.begin(); //可以使用auto自动识别类型
  while (it != v1.end())
  {
    cout << *it << " ";
    it++;
  }
  cout << endl;
  //范围for
  for (auto i : v1)
  {
    cout << i << " ";
  }
  cout << endl;
  //反向迭代器
  std::vector<int>::reverse_iterator rit = v1.rbegin(); //可以使用auto自动识别类型
  while (rit != v1.rend())
  {
    cout << *rit << " ";
    rit++;
  }
  cout << endl;
}

vector空间函数

容量空间 接口说明
size() 获取vector中数据个数
capacity() 获取vector中空间容量大小
empty() 判断是否为空
resize() (重点) 改变vector中size并且设置内容
reserve() (重点) 改变vector中的capacity(空间)大小**(扩容)**
void test3()
{
  vector<int> v1(5, 1);
  cout << "size: " << v1.size() << endl;
  cout << "capacity: " << v1.capacity() << endl;
  if (v1.empty())
  {
    cout << "为空" << endl;
  }
  else
  {
    cout << "不为空" << endl;
  }
  //resize,n比size小
  v1.resize(3);
  for (auto i : v1)
  {
    cout << i << " ";
  }
  cout << endl;
  //resize,n比size大(如果比capacity大就扩容)
  v1.resize(10, 2);
  for (auto i : v1)
  {
    cout << i << " ";
  }
  cout << endl;
  
  //reserve扩容
  cout << "扩容前capacity: " << v1.capacity() << endl;
  v1.reserve(20);
  cout << "扩容后capacity: " << v1.capacity() << endl;
}

vector增删查改

这里再多算一个operator [] (下标访问)。

增删查改 接口说明
push_back() (重点) 尾插
pop_back() (重点) 尾删
find() 查找**(这个不在vector容器内,是算法的接口)**
insert() 在pos位置之前插入数据val(也可以插入n个数据)
erase() 删除pos位置的数据(或者删除一段迭代器区间的数据)
swap() 交换两个vector的数据
operator [] (重点) 下标访问
void test4()
{
  vector<int> v;
  //尾插
  v.push_back(1);
  v.push_back(2);
  v.push_back(3);
  v.push_back(4);
  v.push_back(5);
  v.push_back(6);
  v.push_back(7);
  for (auto i : v)
  {
    cout << i << " ";
  }
  cout << endl;
  //尾删
  v.pop_back();
  v.pop_back();
  for (auto i : v)
  {
    cout << i << " ";
  }
  cout << endl;
  //find查找 
  auto f1 = find(v.begin(), v.end(), 3);//find返回的是迭代器
  cout << *f1 << endl;
  //insert
  v.insert(f1, 2, 66);
  for (auto i : v)
  {
    cout << i << " ";
  }
  cout << endl;
  //erase删除一个数据
  auto f2 = find(v.begin(), v.end(), 1);
  v.erase(f2);
  for (auto i : v)
  {
    cout << i << " ";
  }
  cout << endl;
  //erase删除一段迭代器区间的数据
  auto f3 = find(v.begin(), v.end(), 3);
  auto f4 = find(v.begin(), v.end(), 5);
  v.erase(f3, f4);
  for (auto i : v)
  {
    cout << i << " ";
  }
  cout << endl;
  //swap交换
  vector<int> v1(5, 1);
  v.swap(v1);
  //下标访问
  for (int i = 0; i < v.size(); i++)
  {
    cout << v[i] << " ";
  }
  cout << endl;
}

这里有一个问题,就是迭代器失效问题;在调用reserve、insert或者erase等方法后,之前的迭代器会失效(如果继续使用会出问题)

**解决方法:**在使用过后,记得重新给迭代器赋值。

vector的使用(OJ题)

136. 只出现一次的数字 - 力扣(LeetCode)

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ret=0;
        for(int i=0;i<nums.size();i++)
        {
            ret^=nums[i];
        }
        return ret;
    }
};

118. 杨辉三角 - 力扣(LeetCode)

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>> vv;
        vv.resize(numRows);
        for (int i = 0; i < numRows; i++) {
            // vv[i].resize(i + 1, 0);
            // vv[i][0] = vv[i][i] = 1;
            vv[i].resize(i + 1, 1);
        }
        /*for (int i = 0; i < vv.size(); i++) {
            for (int j = 0; j < vv[i].size(); j++) {
                if (vv[i][j] == 0) {
                    vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];
                }
            }
        }*/
        for (int i = 1; i < vv.size(); i++) {
            for (int j = 1; j < vv[i].size() - 1; j++) {
                vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];
            }
        }
        return vv;
    }
};

17. 电话号码的字母组合 - 力扣(LeetCode)

这个题有一点难度,我们使用多路递归思路,一次递归来解决。

思路

根据输入的数字,找到对于的字符串,然后多路递归,组成不同的字母组合,最后返回vector类型的对象。

以题目给的示例来分析一下:

这样递归,递归到空时(digits中数的取完后),字母组合完成,尾插到vector类对象v当中。

class Solution {
    string StrA[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
public:
    void Func(string digits, int level, string s, vector<string>& v)
    {
        if(level==digits.size())
        {
            if(level)
                v.push_back(s);
            return;
        }
        int num=digits[level]-'0';
        string str=StrA[num];
        for(int i=0;i<str.size();i++)
        {
            Func(digits,level+1,s+str[i],v);
        }     
    }
    vector<string> letterCombinations(string digits) {
        vector<string> ret;
        Func(digits,0,"",ret);
        return ret;
    }
};

vector使用就结束了,使用比较简单,(STL容器的使用比较统一)。

相关文章
|
4月前
|
存储 编译器 C++
【C++】vector介绍+模拟实现
【C++】vector介绍+模拟实现
|
23天前
|
存储 编译器 C语言
【c++丨STL】vector的使用
本文介绍了C++ STL中的`vector`容器,包括其基本概念、主要接口及其使用方法。`vector`是一种动态数组,能够根据需要自动调整大小,提供了丰富的操作接口,如增删查改等。文章详细解释了`vector`的构造函数、赋值运算符、容量接口、迭代器接口、元素访问接口以及一些常用的增删操作函数。最后,还展示了如何使用`vector`创建字符串数组,体现了`vector`在实际编程中的灵活性和实用性。
48 4
|
5天前
|
存储 对象存储 C++
C++ 中 std::array<int, array_size> 与 std::vector<int> 的深入对比
本文深入对比了 C++ 标准库中的 `std::array` 和 `std::vector`,从内存管理、性能、功能特性、使用场景等方面详细分析了两者的差异。`std::array` 适合固定大小的数据和高性能需求,而 `std::vector` 则提供了动态调整大小的灵活性,适用于数据量不确定或需要频繁操作的场景。选择合适的容器可以提高代码的效率和可靠性。
23 0
|
9天前
|
存储 编译器 C语言
【c++丨STL】vector模拟实现
本文深入探讨了 `vector` 的底层实现原理,并尝试模拟实现其结构及常用接口。首先介绍了 `vector` 的底层是动态顺序表,使用三个迭代器(指针)来维护数组,分别为 `start`、`finish` 和 `end_of_storage`。接着详细讲解了如何实现 `vector` 的各种构造函数、析构函数、容量接口、迭代器接口、插入和删除操作等。最后提供了完整的模拟实现代码,帮助读者更好地理解和掌握 `vector` 的实现细节。
18 0
|
2月前
|
存储 C++ 索引
【C++打怪之路Lv9】-- vector
【C++打怪之路Lv9】-- vector
26 1
|
2月前
|
安全 测试技术 C++
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化2
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化
75 6
|
2月前
|
安全 测试技术 C++
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化1
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化
88 7
|
2月前
|
编译器 C++
【C++】—— vector模拟实现
【C++】—— vector模拟实现
|
2月前
|
编译器 C语言 C++
【C++篇】解密 STL 动态之魂:全面掌握 C++ vector 的高效与优雅
【C++篇】解密 STL 动态之魂:全面掌握 C++ vector 的高效与优雅
58 3
|
2月前
|
C++
【C++】C++ STL探索:Vector使用与背后底层逻辑(三)
【C++】C++ STL探索:Vector使用与背后底层逻辑