如何直接获取vector的子数组
时间: 2024-09-20 18:12:42 浏览: 58
在C++中,如果你有一个`std::vector<T>`类型的容器,并想要获取其部分元素作为另一个子向量,可以使用`substr()`函数或者`begin()`和`end()`迭代器来创建一个新的`vector`。以下是两种方法:
1. 使用`substr()`函数:
```cpp
std::vector<T> parent_vector; // 假设这是你的原向量
size_t start_index = 0; // 起始索引
size_t length = 5; // 子数组长度
// 创建子向量
std::vector<T> sub_array = parent_vector.substr(start_index, length);
```
这将从`parent_vector`的起始索引开始截取指定长度的连续元素。
2. 使用`begin()`和`end()`迭代器:
```cpp
std::vector<T>::iterator begin_sub = parent_vector.begin() + start_index;
std::vector<T>::iterator end_sub = begin_sub + length;
// 创建子向量并确保不会超出边界
std::vector<T> sub_array(parent_vector.begin(), end_sub);
```
这里首先找到起始位置的迭代器,然后移动到结束位置,再创建一个新的`vector`,包含这个区间的所有元素。
相关问题
c++vector子数组
### C++ 中 `vector` 的子数组操作
#### 获取子数组
为了获取 `vector` 的子数组,在 C++ 中可以通过迭代器来实现。下面展示了一个例子,其中定义了一种方法来提取给定范围内的元素并创建一个新的 `vector`。
```cpp
#include <iostream>
#include <vector>
std::vector<int> getSubArray(const std::vector<int>& vec, int start, int end) {
if (start < 0 || end >= static_cast<int>(vec.size()) || start > end) {
throw std::out_of_range("Invalid range");
}
return std::vector<int>(vec.begin() + start, vec.begin() + end + 1);
}
```
此代码片段展示了如何通过指定起始位置和结束位置来获得原向量的一个部分[^4]。
#### 修改子数组
如果想要修改某个特定范围内元素的值,则可以直接遍历该区间并对每个元素执行赋值或其他所需的操作:
```cpp
void modifySubArray(std::vector<int>& vec, int start, int end, const std::function<void(int&)>& func) {
for (int i = start; i <= end && i < vec.size(); ++i) {
func(vec[i]);
}
}
```
这段程序接受一个 lambda 表达式或者其他形式的一元函数对象作为参数,允许灵活地改变选定区域内的数值。
#### 复制子数组至另一位置
有时可能需要将一部分的数据复制到同一个或不同 `vector` 的其他地方。这同样可以借助迭代器完成:
```cpp
template<typename T>
void copySubArrayToPosition(std::vector<T>& srcVec, int startPos, int length, std::vector<T>& destVec, int destPos) {
auto itBegin = srcVec.cbegin() + startPos;
auto itEnd = itBegin + length;
if (destPos + length > destVec.size())
destVec.resize(destPos + length);
std::copy(itBegin, itEnd, destVec.begin() + destPos);
}
```
上述模板化版本适用于任何内置类型以及自定义类型的 `vector`,并且会在必要时调整目标容器大小以容纳新加入的内容。
C++ 链表 vector
### C++ 中 `std::list` 和 `std::vector` 的用法及区别
#### 使用头文件
为了使用 `std::list` 或者 `std::vector`,需要包含相应的头文件。
对于 `std::vector`:
```cpp
#include <vector>
```
对于 `std::list`:
```cpp
#include <list>
```
#### 创建对象实例
创建一个空的 `std::vector<int>` 对象:
```cpp
std::vector<int> vec;
```
初始化含有特定数量元素的 `std::vector<int>` :
```cpp
std::vector<int> vec2(4); // 含有四个默认初始化为0的整数[^1]
```
通过指定初始值来定义 `std::vector<int>` :
```cpp
std::vector<int> vec3(4, 10); // 初始化含四次重复数值10的向量 [10 10 10 10]
```
利用另一个相同类型的容器范围构建新的 `std::vector<int>` 实例:
```cpp
std::vector<int> vec4(vec3.begin(), vec3.end()); // 构建新向量 [10 10 10 10]
```
复制已存在的 `std::vector<int>` 来建立新实体:
```cpp
std::vector<int> vec5(vec3); // 新向量同样为 [10 10 10 10]
```
采用列表初始化语法设定 `std::vector<int>` 初始成员:
```cpp
std::vector<int> vec6 = {10, 20, 30, 40}; // 定义并赋初值给vec6 [10 20 30 40]
```
针对 `std::list<T>` 类型,则可以通过如下方式声明和初始化链表变量:
```cpp
std::list<int> lst; // 声明一个空的整数链表
lst.push_back(1);
lst.push_front(2);
// 插入更多元素...
```
#### 主要特性对比
- **内存分配**: `std::vector` 是连续线性数组,在动态增长时可能涉及重新分配整个内部缓冲区;而 `std::list` 存储的是节点组成的双向循环链接结构,各节点之间不必相邻存放于物理地址空间内。
- **访问速度**: 访问 `std::vector` 内部任意位置的数据效率较高(O(1)),因为可以直接计算偏移获取目标项指针。但是 `std::list` 只能逐一遍历直至找到所需项目(O(n))。
- **插入/删除性能**: 当涉及到频繁地在序列中间执行增删动作时,`std::list` 表现更优,因为它只需调整前后两个邻接单元之间的连接关系即可完成操作。然而,如果是在末端追加或弹出单个元素的情况下,两者差异不大甚至有时 `std::vector` 还会更快一些。
- **迭代器稳定性**: 如果对 `std::vector` 执行某些改变大小的操作可能会使现有迭代失效,比如调用了 push_back() 导致容量不足触发扩容重定位过程。相反,除非显式清除掉部分子区间内的全部结点,否则 `std::list` 上获得的有效迭代总是安全可靠的。
综上所述,选择哪种容器取决于具体应用场景的需求以及预期的工作负载模式[^2]。
阅读全文