繁体   English   中英

地图,成对向量还是两个向量……?

[英]Map, pair-vector or two vectors…?

我通读了一些帖子和“ Wiki”,但仍无法确定哪种方法适合我的问题。

我创建了一个名为Sample的类,其中包含一定数量的化合物(可以说这是Nuclide另一类),并且具有一定的相对数量(两倍)。

因此,类似(pseudo):

class Sample {
    map<Nuclide, double>;
}

如果样本中有Ba-133Co-60Cs-137核素,则必须在代码中准确使用这些名称才能访问地图中的这些核素。 但是,我唯一需要做的就是遍历地图以执行计算(它们不关心哪个核素),因此,我将使用for循环。 我想在不关注键名的情况下进行迭代,因此,我需要为地图使用迭代器,对吗?

一个替代方法是vector<pair<Nuclide, double> >

class Sample {
    vector<pair<Nuclide, double> >;
}

或只是两个独立的向量

Class Sample {
    vector<Nuclide>;
    vector<double>;
}

而在最后一个选项中,核素与其数量之间的联系将是“元信息”,仅由相应向量中的位置给出。

由于我缺乏丰富的经验,因此请提出关于选择哪种方法的建议。 我想让所有可用化合物的迭代过程变得轻松快捷,同时保持相应键和值的逻辑结构。

PS .:样本中的compunds数量可能很低(1到5)! PPS .:是否可以通过某些const语句修改最后一个选项,以防止更改并因此保持正确的顺序?

如果迭代需要快速,那么您就不需要std::map<...> :它的迭代是一条遍地开花的树,很快就会变糟。 std::map<...>实际上只有在序列有很多突变并且需要按键排序的序列时才是合理的。 如果您有突变但不关心顺序std::unordered_map<...>通常是更好的选择。 不过,两种地图都假设您正在按键查找事物。 从您的描述来看,我并不是真的如此。

std::vector<...>快速迭代。 但是,它对于查找不是理想的。 如果将其保持有序,则可以使用std::lower_bound()进行std::map<...>类似的查找(即,复杂度也是O(log n) ),但是要努力保持它排序可能会使该选项过于昂贵。 但是,它是用于将一堆被迭代的对象保持在一起的理想容器。

是否需要一个std::vector<std::pair<...>>还是两个std::vector<...> s取决于您如何访问元素:如果元素的两个部分都已绑定要一起访问,您需要一个std::vector<std::pair<...>>因为这样可以保留一起访问的数据。 另一方面,如果您通常仅访问两个组件之一,则使用两个单独的std::vector<...> s将使迭代速度加快,因为更多的迭代元素适合于高速缓存行,尤其是当它们合理时小如double s。

无论如何,我建议不要将外部结构暴露给外界,而应该提供一个接口,让您以后可以更改基础表示形式。 也就是说,为了获得最大的灵活性,您不想将表示形式烘烤到所有代码中。 例如,如果您使用访问器函数对象(以BGL表示 属性图或以Eric Niebler的Range Proposal表示投影 )来访问基于迭代器的元素,而不是访问元素,则无需触摸即可更改内部布局任何算法(不过,您都需要重新编译代码):

// version using std::vector<std::pair<Nuclide, double> >
// - it would just use std::vector<std::pair<Nuclide, double>::iterator as iterator
auto nuclide_projection = [](Sample::key& key) -> Nuclide& {
    return key.first;
}
auto value_projecton = [](Sample::key& key) -> double {
    return key.second;
}

// version using two std::vectors:
// - it would use an iterator interface to an integer, yielding a std::size_t for *it
struct nuclide_projector {
    std::vector<Nuclide>& nuclides;
    auto operator()(std::size_t index) -> Nuclide& { return nuclides[index]; }
};
constexpr nuclide_projector nuclide_projection;
struct value_projector {
    std::vector<double>& values;
    auto operator()(std::size_t index) -> double& { return values[index]; }
};
constexpr value_projector value_projection;

有了这些就位,例如,仅在它们之上运行并打印它们的算法可能如下所示:

template <typename Iterator>
void print(std::ostream& out, Iterator begin, Iterator end) {
    for (; begin != end; ++begin) {
         out << "nuclide=" << nuclide_projection(*begin) << ' '
             << "value=" << value_projection(*begin) << '\n';
    }
}

两种表示完全不同,但是访问它们的算法完全独立。 这样,尝试不同的表示形式也很容易:只需更改表示形式和访问它的算法的粘合即可。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM