交换向量的值和索引
Swap values and indexes of a vector
我有一个std::vector<int>
,它具有从0到N的连续洗牌值,并且希望尽可能有效地交换每个值与其在向量中的位置。
的例子:
v[6] = 3;
是
v[3] = 6;
这是一个简单的问题,但我不知道如何处理它,以使它变得微不足道,最重要的是,非常快。非常感谢您的建议。
给定N
在编译时,并且给定数组包含[0,N)
中的每个索引正好一次,它是相对直接的(只要它不需要在适当的位置,就像上面的评论中提到的):
为v'[n] = find_index(v, n)
构造一个新的数组并赋值给旧的数组。
在这里,我使用可变模板和std::index_sequence
将其滚动到一个单一的赋值:
template<typename T, std::size_t N>
std::size_t find_index(const std::array<T,N>& arr, std::size_t index) {
return static_cast<std::size_t>(std::distance(arr.begin(), std::find(arr.begin(), arr.end(), index)));
}
template<typename T, std::size_t N, std::size_t... Index>
void swap_index_value(std::array<T,N>& arr, std::index_sequence<Index...> seq){
arr = { find_index(arr, Index)... };
}
template<typename Integer, std::size_t N>
void swap_index_value(std::array<Integer,N>& arr) {
swap_index_value(arr, std::make_index_sequence<N>{});
}
这看起来并不复杂。对[0,N)
中的每个n调用find_index(arr, n)
总共需要N * (N+1)/2次比较(std::sort
只需要N * log(N))。
然而,由于我们知道数组中存在每个索引,我们可以直接填充一个索引数组当我们遍历原始数组时,假设T是整型,我们也可以跳过一些std::size_t <-> T转换:
template<typename T, std::size_t N>
void swap_index_value(std::array<T,N>& arr){
std::array<T, N> indices;
for (T i = 0; i < N; ++i)
indices[arr[i]] = i;
arr = indices;
}
我们仍然使用两倍的空间并对数组进行随机顺序的写操作,但实际上我们只需要2*N个赋值,而且代码比以前更简单了。
或者,我们也可以std::sort
,如果我们保留一个副本做查找:
template<typename T, std::size_t N>
void swap_index_value(std::array<T,N>& arr){
std::sort(arr.begin(), arr.end(), [copy = arr](const T& lhs, const T& rhs) {
return copy[lhs] < copy[rhs];
});
}
这里是第一个版本,第二个版本在这里,
测试哪一个更快,留给读者作为练习;)
相关文章:
- 在C++中调整向量中的索引
- 给定一个向量,如何找到该向量的所有子集和的原始索引
- 将转换字符键入 int 以用作向量C++的索引
- 在对向量中查找元素的索引
- 如何检查类实例向量的索引是否为空
- 如何根据排序索引的向量对 std::index 集进行排序?
- C++ 中字符串向量的索引
- 如何在C++中返回向量的从零开始的索引
- 向量索引变量声明(size_t 或 std::vector<DATATYPE>::size_type)
- 特征获取索引数组,其中向量中的值为真(不需要循环)
- 引用向量中的特定索引
- 在C++中从距离矩阵创建索引向量的最快方法
- 在python gdb脚本中索引c ++向量
- 使用索引向量擦除另一个向量的索引
- 根据索引向量对向量重新排序 - 更新
- C++11将智能指针的索引向量作为类的成员
- 使用auto关键字填充双索引向量
- C++对不带lambda的索引向量进行排序
- 如何从Eigen中的索引向量中提取子向量(Eigen::Vector)
- 通过索引向量对犰狳矩阵的所有列进行排序的最佳方法