C++ C++;用于存储两组唯一元素之间的多个关系的数据结构

C++ C++;用于存储两组唯一元素之间的多个关系的数据结构,c++,dictionary,boost,bimap,boost-bimap,C++,Dictionary,Boost,Bimap,Boost Bimap,我正在做一个项目,我有两套独特的元素。一个集合中的任何元素都可能与另一个集合中的任何元素相关 例如: 集合1:{A,B,C} 集合2:{1,2,3,4} 允许的关系: (A,1)(A,3) (B,1)(B,4) (C,1)(C,3)(C,4) 单个关系表示为一对括号内的两个集合元素 在我的特定项目中,两个集合的元素都是对象,我希望对存储的所有对象的所有引用都解析为一个对象(例如,包含A的所有关系都将引用同一个对象A,对关系另一侧的其他集合的引用也是如此) 我正在考虑使用Boostbimap来解决

我正在做一个项目,我有两套独特的元素。一个集合中的任何元素都可能与另一个集合中的任何元素相关

例如:

集合1:{A,B,C}

集合2:{1,2,3,4}

允许的关系:

(A,1)(A,3)

(B,1)(B,4)

(C,1)(C,3)(C,4)

单个关系表示为一对括号内的两个集合元素

在我的特定项目中,两个集合的元素都是对象,我希望对存储的所有对象的所有引用都解析为一个对象(例如,包含A的所有关系都将引用同一个对象A,对关系另一侧的其他集合的引用也是如此)

我正在考虑使用Boost
bimap
来解决这个问题。我在研究bimap左右半部分可能使用的集合类型,以及两组集合之间的关系,并一直试图确定哪些集合是正确的

对于
bimap
的左半部分和右半部分,我认为
CollectionType
集合应该是正确的,因为我的两组对象都是集合,我不想在
bimap
中复制任何元素

但是,当我在实践中尝试这种方法时,在插入关系(A,1)之后,我最终无法插入关系(B,1),因为插入必须在左视图和右视图中都有效,才能发生。为了解决这个问题,我将两半的
CollectionType
更改为
multiset\u of
。所有值都正确插入,但是,这是否意味着我的
bimap
现在具有原始集合元素的重复副本

为了尝试纠正这一点,我开始考虑更改
bimap
两半之间关系的集合类型。由于关系类型的集合类型默认为
bimap
左半部分的集合类型,因此我认为
multiset\u of
不正确,并将其指定为
set\u of
。但是,我不确定这是否解决了我的原始问题,即从原始集合中复制多个对象


我真正需要的是查看集合2中与集合1中的元素相关的所有对象。Boost
bimap
对我来说是正确的路线吗?我选择的集合和关系类型是否正确?顺便说一句,我正在尝试自定义我的地图,使其具有快速的搜索时间,而不必考虑插入时间(删除和修改永远不会发生,地图将初始化,然后仅用于此后的查找)。我应该只写一个自定义数据结构吗?

这让我觉得更多的是图形问题,最好更直接地建模:

struct nodeB;

struct nodeA {
    char label;
    std::vector<nodeB *> assocs;
};

struct nodeB { 
    int label;
    std::vector<nodeA *> assocs;
};
struct节点b;
结构节点{
字符标签;
std::向量关联;
};
结构节点{
int标签;
std::向量关联;
};

从这里开始,我想您需要一个类来管理每种类型的集合,并处理添加节点以确保正确维护不变量。

我完全同意Jerry的回答。如果你试图对图表建模,考虑使用邻接列表、边缘列表或矩阵表示,例如:

Paul的回答有点摇摆不定,因此,下面是一个使用Boost Multi Index的示例:

#include <iostream>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/ordered_index.hpp>

struct T1 {
    std::string name;
    bool operator<(T1 const& o) const { return name < o.name; }
};
struct T2 {
    int id;   
    bool operator<(T2 const& o) const { return id < o.id; }
};

namespace bmi = boost::multi_index;

struct Relation {
    T1 const* key1;
    T2 const* key2;

    std::string const& name() const { return key1->name; }
    int                id  () const { return key2->id;   }

    friend std::ostream& operator<<(std::ostream& os, Relation const& r) {
        return os << "(" << r.name() << ", " << r.id() << ")";
    }
};

using RelationTable = bmi::multi_index_container<Relation,
      bmi::indexed_by<
        bmi::ordered_unique<bmi::tag<struct by_composite>, 
            bmi::composite_key<Relation, 
                bmi::const_mem_fun<Relation, std::string const&, &Relation::name>,
                bmi::const_mem_fun<Relation, int, &Relation::id>
            >
        >
    > >;

#include <set>

int main() {
    using namespace std;
    set<T1> set1 { {"A"}, {"B"}, {"C"} };
    set<T2> set2 { {1}, {2}, {3}, {4} };

    // convenient data entry helpers
    auto lookup1 = [&set1](auto key) { return &*set1.find(T1{key}); }; // TODO error check?
    auto lookup2 = [&set2](auto key) { return &*set2.find(T2{key}); };
    auto relate  = [=](auto name, auto id) { return Relation { lookup1(name), lookup2(id) }; };
    // end helpers

    RelationTable relations {
        relate("A", 1), relate("A", 3),
        relate("B", 1), relate("B", 4),
        relate("C", 1), relate("C", 3), relate("C", 4),
    };

    for (auto& rel : relations)
        std::cout << rel << " ";
}

保持乐观。我也是,我在问题中嗅到了这一点。事实上,我发现,从集合a中指向对象的指针到集合B中的引用,使用
std::multimap
对我来说是最简单/最好的方法。不过,出于好奇,这个问题仍然存在。
(A, 1) (A, 3) (B, 1) (B, 4) (C, 1) (C, 3) (C, 4)