有很多矢量排序在一起

时间:2017-07-12 22:56:39

标签: c++ sorting vector stdvector

我有三个相同大小的矢量(约100万个项目):

std::vector<wstring> name;
std::vector<int> x;
std::vector<int> y;

可以看作是三个&#34;列&#34;。

如何排序A-&gt; Z向量name

std::sort(name.begin(), name.end())

但是相应地对矢量xy进行了排序?

示例:

name  x  y                 name  x  y
BCD   7  9                 ABC   4  3
ZYX   1  4        =>       BCD   7  9
ABC   4  3                 ZYX   1  4

使用std::vector的好处是,我可以通过仅保留索引列表轻松选择/过滤大vector中的一些项目(例如:let&#39; s保留项目12,1872,2834,1831)。 我考虑过使用std::map,但我担心它不会对此有效:如何保留一个元素列表以保留在地图中?

2 个答案:

答案 0 :(得分:4)

有几种可能的方法可以做到这一点。最简单的方法是将namexy包装在结构中:

struct Person {
    std::wstring name;
    int x;
    int y;
};

然后你可以拥有std::vector<Person> people并进行排序(假设是C ++ 14)

std::sort(people.begin(), people.end(),
    [](auto const& lhs, auto const& rhs) { return lhs.name < rhs.name; });

但是,如果您知道这会导致性能问题,因为缓存中的元素数量较少(也就是说,您经常只迭代x或仅y并且您是在非常有限的环境中,例如高性能游戏),我建议只排序一个向量。除非你知道自己在做什么,否则你需要对这两个选项进行基准测试。

基本上,有一个跟踪排序的向量:

std::vector<std::wstring> name;
std::vector<int> x;
std::vector<int> y

std::vector<std::size_t> ordering(name.size());
std::iota(ordering.begin(), ordering.end(), 0);

std::sort(ordering.begin(), ordering.end(),
    [&](auto const& lhs, auto const& rhs) {
        return name[lhs] < name[rhs];
    });

然后,您可以简单地遍历ordering以按新顺序浏览每个并行向量。

额外的间接水平可能会降低效率。例如,CPU可能认为存在数据依赖关系,而没有数据依赖关系。此外,我们在ordering中跟踪的额外数据可以轻松地在缓存中占用足够的空间来抵消分离namexy的好处;您需要了解目标架构和配置文件的规格才能确定。

如果您希望以这个新顺序继续迭代它们,您可能希望使用此ordering向量来对其他向量进行排序,因为对元素的访问将变为随机。这将抵消保持向量分离的好处(除非向量足够小以适应缓存)。

最简单的方法是创建一个新的向量:

std::vector<std::wstring> newNames;
newNames.reserve(name.size());

for (auto i : ordering) {
    newNames.push_back(name[i]);
}

如果在初始化期间进行排序,那么重建像这样的向量可能是你想要做的。

答案 1 :(得分:1)

听起来你想要一个结构来保持数据在一起。例如:

struct MyData
{
  wstring name;
  int x;
  int y;
};

...
std::vector<MyData> data;

从那里开始,您需要一个比较函数来执行自定义排序,以确保您从要排序的字段中进行排序:

std::sort(data.begin(), data.end(), compareByName);

bool compareByName(const MyData& lhs, const MyData& rhs)
{
    return lhs.name < rhs.name; // This can be whatever
}