C与Python中的Vector详解:从基础到高级特性的全面解析
C++与Python中的Vector详解:从基础使用到高级特性
1. C++中的Vector:动态数组的强大实现
1.1 Vector基本概念
在C++中,std::vector
是标准模板库(STL)提供的一种序列容器,它能够动态增长和缩小,同时保持元素在内存中的连续存储。与传统的C风格数组相比,vector提供了更多的灵活性和功能:
要使用vector,需要包含头文件:
#include <vector>
1.2 Vector的创建与初始化
C++中的vector提供了多种初始化方式:
// 1. 创建空vector
std::vector<int> vec1;
// 2. 创建包含5个元素的vector,初始值为默认值(0)
std::vector<int> vec2(5);
// 3. 创建包含5个元素的vector,每个元素初始值为10
std::vector<int> vec3(5, 10);
// 4. 通过初始化列表创建vector
std::vector<int> vec4 = {1, 2, 3, 4, 5};
// 5. 通过数组创建vector
int arr[] = {1, 2, 3, 4, 5};
std::vector<int> vec5(arr, arr + 5);
// 6. 通过另一个vector创建
std::vector<int> vec6(vec5);
1.3 Vector的常用操作
1.3.1 添加元素
std::vector<int> vec;
// 在末尾添加元素
vec.push_back(10);
// 在指定位置插入元素
vec.insert(vec.begin() + 1, 20); // 在第二个位置插入20
// 插入多个相同元素
vec.insert(vec.end(), 3, 30); // 在末尾插入3个30
// 通过范围插入
int arr[] = {40, 50};
vec.insert(vec.begin(), arr, arr + 2); // 在开头插入数组元素
1.3.2 访问元素
// 使用下标访问
int first = vec[0];
// 使用at()访问,会进行边界检查
int second = vec.at(1);
// 访问首尾元素
int front = vec.front();
int back = vec.back();
// 使用迭代器访问
for(auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " ";
}
// 使用范围for循环访问(C++11)
for(int num : vec) {
std::cout << num << " ";
}
1.3.3 删除元素
// 删除末尾元素
vec.pop_back();
// 删除指定位置元素
vec.erase(vec.begin() + 1);
// 删除范围元素
vec.erase(vec.begin() + 2, vec.begin() + 4);
// 清空vector
vec.clear();
1.3.4 大小与容量
// 获取当前元素数量
size_t size = vec.size();
// 获取当前分配的内存容量
size_t cap = vec.capacity();
// 检查是否为空
bool isEmpty = vec.empty();
// 调整大小
vec.resize(10); // 调整为10个元素,新增元素默认初始化
vec.resize(15, 100); // 调整为15个元素,新增元素初始化为100
// 预分配内存
vec.reserve(100); // 预分配至少100个元素的空间
1.4 Vector的内存管理与性能
1.4.1 内存增长策略
当vector的size等于capacity时,再添加新元素会触发内存重新分配。C++标准没有规定具体的增长策略,但常见的实现是指数增长(通常是2倍或1.5倍)。这种策略使得在末尾插入元素的摊还时间复杂度为O(1)。
std::vector<int> v;
for(int i = 0; i < 100; ++i) {
v.push_back(i);
std::cout << "Size: " << v.size()
<< ", Capacity: " << v.capacity() << std::endl;
}
1.4.2 内存释放
vector的内存空间只增不减,即使调用clear()
或erase()
,capacity也不会减少。要真正释放内存,可以使用swap技巧:
// 方法1:与临时空vector交换
std::vector<int>().swap(vec);
// 方法2:使用shrink_to_fit(C++11)
vec.shrink_to_fit();
1.4.3 性能特点
1.5 Vector的高级特性
1.5.1 迭代器
vector支持多种迭代器:
// 正向迭代器
for(auto it = vec.begin(); it != vec.end(); ++it) { /*...*/ }
// 反向迭代器
for(auto rit = vec.rbegin(); rit != vec.rend(); ++rit) { /*...*/ }
// 常量迭代器(C++11)
for(auto cit = vec.cbegin(); cit != vec.cend(); ++cit) { /*...*/ }
1.5.2 二维Vector
// 创建5行6列的二维vector,初始值为0
std::vector<std::vector<int>> matrix(5, std::vector<int>(6, 0));
// 访问元素
matrix[1][2] = 10;
// 动态添加行
matrix.push_back(std::vector<int>(6, -1));
1.5.3 算法支持
vector可以与STL算法完美配合:
#include <algorithm>
// 排序
std::sort(vec.begin(), vec.end());
// 查找
auto it = std::find(vec.begin(), vec.end(), 42);
// 反转
std::reverse(vec.begin(), vec.end());
// 移除特定元素
vec.erase(std::remove(vec.begin(), vec.end(), 99), vec.end());
2. Python中的Vector:多样化的实现方式
2.1 Python内置列表与Vector概念
Python没有内置的vector
类型,但它的list
已经提供了类似vector的动态数组功能。不过,Python的list与C++的vector有一些关键区别:
2.2 NumPy中的Vector:高性能数值计算
对于数值计算,NumPy提供的ndarray
是最接近C++ vector的实现:
import numpy as np
# 创建NumPy数组(vector)
arr = np.array([1, 2, 3, 4, 5])
# 向量化操作
arr = arr * 2 # 每个元素乘以2
arr = arr + 1 # 每个元素加1
NumPy数组的关键特性:
2.2.1 向量化(Vectorization)
NumPy的核心优势是向量化,即对整个数组执行操作而不需要显式循环:
# 低效的Python循环
result = []
for x in my_list:
result.append(x * 2)
# 高效的NumPy向量化操作
result = np.array(my_list) * 2
向量化的优势:
2.2.2 性能对比
import timeit
setup = '''
import numpy as np
my_list = list(range(10000))
'''
# Python列表循环
list_time = timeit.timeit('[x*2 for x in my_list]', setup=setup, number=1000)
# NumPy向量化
numpy_time = timeit.timeit('np.array(my_list)*2', setup=setup, number=1000)
print(f"List comprehension: {list_time:.4f} sec")
print(f"NumPy vectorization: {numpy_time:.4f} sec")
典型输出:
List comprehension: 0.3827 sec
NumPy vectorization: 0.0125 sec
2.3 collections.deque:双端队列
对于需要频繁从两端添加/删除元素的场景,collections.deque
是更好的选择:
from collections import deque
# 创建deque
d = deque([1, 2, 3])
# 添加元素
d.append(4) # 右端添加
d.appendleft(0) # 左端添加
# 删除元素
d.pop() # 右端删除
d.popleft() # 左端删除
deque的特点:
2.4 其他Vector实现
2.4.1 array模块
对于基本数值类型,array
模块提供了更紧凑的存储:
from array import array
# 创建一个整数数组
int_array = array('i', [1, 2, 3, 4, 5])
2.4.2 自定义Vector类
可以创建类似C++ vector的Python类:
class Vector:
def __init__(self):
self._items = []
def push_back(self, item):
self._items.append(item)
def pop_back(self):
return self._items.pop()
def __getitem__(self, index):
return self._items[index]
def __len__(self):
return len(self._items)
3. C++ Vector与Python"Vector"的对比
特性 | C++ std::vector | Python list | NumPy array | collections.deque |
---|---|---|---|---|
动态大小 | 是 | 是 | 是 | 是 |
内存连续性 | 是 | 否 | 是 | 否 |
类型限制 | 同类型元素 | 任意类型 | 同类型元素 | 任意类型 |
随机访问 | O(1) | O(1) | O(1) | O(1) |
末尾插入/删除 | O(1)摊还 | O(1) | O(1) | O(1) |
开头插入/删除 | O(n) | O(n) | O(n) | O(1) |
中间插入/删除 | O(n) | O(n) | O(n) | O(n) |
内存预分配 | 支持(reserve) | 不支持 | 支持 | 支持(maxlen) |
多维支持 | 支持(vector<vector>) | 支持(list of lists) | 支持(ndarray) | 支持(deque of deques) |
并行计算优化 | 无 | 无 | 有 | 无 |
4. 实际应用建议
4.1 何时使用C++ vector
4.2 何时使用Python替代方案
4.3 性能优化技巧
4.3.1 C++ vector优化
- 预分配内存:如果知道大致大小,先用
reserve()
预分配 - 避免不必要的拷贝:使用移动语义或引用
- 选择合适的插入位置:优先在末尾操作
- 使用emplace_back:避免临时对象
- 考虑自定义分配器:对于特殊内存需求
4.3.2 Python"Vector"优化
- 优先使用NumPy:对于数值计算
- 避免循环:尽量使用向量化操作
- 选择合适结构:根据操作模式选择list或deque
- 使用视图而非拷贝:NumPy的切片操作
- 考虑内存布局:NumPy的C顺序与F顺序
5. 总结
C++的std::vector
和Python中的各种"vector-like"结构都提供了动态数组的功能,但它们在实现和性能特性上有显著差异。C++ vector提供了更精细的内存控制和更高的性能,特别适合系统编程和高性能计算。Python则提供了更灵活的数据结构选择,适合快速开发和原型设计。
理解这些数据结构的内在特性和适用场景,可以帮助开发者根据具体需求做出最佳选择,编写出既高效又易于维护的代码。
作者:阿牛的药铺