【发布时间】:2015-06-07 10:13:52
【问题描述】:
我有一个vector<uint64_t> keys 和一个vector<char> vals,大小都是N。我想根据keys 中的条目对keys 和vals 进行排序。
一个明显的解决方案是复制到vector<pair<uint64_t, char>>,对其进行排序,然后将排序后的数据复制回来,但我想避免复制,我想避免对齐填充:sizeof(pair<uint64_t, char>) 是2*sizeof(uint64_t) ,或 16 个字节,由于对齐;远远超过所需的 9 个字节。
也就是说,虽然下面的C++11实现是正确的,但是效率不够:
#include <algorithm>
#include <tuple>
using namespace std;
void aux_sort(vector<uint64_t> & k, vector<char> & v) {
vector<pair<uint64_t, char> > kv(k.size());
for (size_t i = 0; i < k.size(); ++i) kv[i] = make_pair(k[i], v[i]);
sort(kv.begin(), kv.end());
for (size_t i = 0; i < k.size(); ++i) tie(k[i], v[i]) = kv[i];
}
虽然下面的 C++11 实现是正确的,但我想使用 std::sort 而不是手动编写自己的排序算法:
#include <algorithm>
using namespace std;
void aux_sort(vector<uint64_t> & k, vector<char> & v) {
for (size_t i = 0; i < k.size(); ++i)
for (size_t j = i; j--;)
if (k[j] > k[j + 1]) {
iter_swap(&k[j], &k[j + 1]);
iter_swap(&v[j], &v[j + 1]);
}
}
(编辑添加,以响应@kfsone)虽然以下实现是正确的,但它不是就地的,因为根据indices 的排列需要一个副本(或者,一个非常复杂的就地线性时间我不会实现的置换算法):
#include <algorithm>
#include <tuple>
using namespace std;
void aux_sort(vector<uint64_t> & k, vector<char> & v) {
vector<size_t> indices(k.size());
iota(indices.begin(), indices.end(), 0);
sort(indices.begin(), indices.end(),
[&](size_t a, size_t b) { return k[a] < k[b]; });
vector<uint64_t> k2 = k;
vector<char> v2 = v;
for (size_t i = 0; i < k.size(); ++i)
tie(k[i], v[i]) = make_pair(k2[indices[i]], v2[indices[i]]);
}
将诸如std::sort 之类的 STL 算法应用于就地键/值对序列的最简单方法是什么,键和值存储在单独的向量中?
背景:我的应用程序正在读取代表地形的大型(40 000 x 40 000)栅格,一次一行。一个栅格为每个单元分配一个介于 0 和 10 000 000 之间的标签,以便标签是连续的,另一个栅格为每个单元分配一个介于 0 和 255 之间的值。我想以有效的方式对每个标签的值求和,我认为最快的方法是对标签行进行排序,并且对于排序过程中的每个交换,在值行中应用相同的交换。我想避免手动编码 std::sort、std::set_intersection 和其他代码。
【问题讨论】:
-
您始终可以为
vector k创建一个索引向量,对索引进行排序,然后将其用作vector v值的跳转表。 -
您对解决方案进行所有限制的目的是什么?你想节省时间吗?内存?
-
我认为您可以创建一个“外观”对象,其中包含对
keys和vals的引用(或者更好的是,直接链接到下划线内存位置),实现迭代器、比较和交换,以及然后在上面应用sort。 -
@KarolyHorvath 这叫 zip 迭代器,不是吗?