像C ++数据结构的数据库

时间:2018-02-04 06:33:53

标签: c++

我查看了类似这样的问题,但似乎大多数答案都建议使用类似sqlite的内存数据库。也许这是唯一真正的解决方案,但无论如何我都会问。

我有许多记录如下:

struct record
{
    int id;
    int type;
    // bunch of other data
}

问题涉及将一些这些存储在一个数据结构中,以便进行有效的运行时查询,如

GetAllForId(int)
GetAllOfType(int)
GetAllOfTypeAndId(int,int)

给定'id'可能有多个'type'记录 对于不同的'id',可以有多个'type'记录

我还希望能够轻松修改任何

结果中的值
GetAllOfTypeAndId(int,int)

当然,以(优选地)低成本进行插入和删除。虽然插入很少,所以我可以在这里吃一点费用。

作为参考,我尝试了以下解决方案:

multimap<type,record>

然后迭代所有记录以找到相关类型之一。感觉非常麻烦,尤其是在执行GetAllOfTypeAndId查询时,对GetAllOfId查询有用

map<id,map<type,record>>

允许良好的GetAllOfTypeAndId查询,但无法提供对GetAllofType的正确访问

不幸的是,由于这个项目的性质,我可能无法使用关系数据库系统,即使它在内存中。

2 个答案:

答案 0 :(得分:2)

听起来你想要MultiIndex。 Joaquin M Lopez提供了一个出色的数据结构,它允许跨多个字段,成员函数或结构/类的其他属性的索引。

在您的情况下,我们可以执行以下操作:

struct record
{
    int id;
    int type;
    // bunch of other data
};

struct id_tag {};
struct type_tag {};

using record_container = boost::multi_index_container<
    record,
    boost::indexed_by<
        boost::hashed_unique<
            boost::multi_index::tag<id_tag>,
            boost::multi_index::member<record, int, &record:id>
        >,
        boost::hashed_non_unique<
            boost::multi_index::tag<type_tag>,
            boost::multi_index::member<record, int, &record:type>
        >
    > 
>;

我们现在可以从ID的唯一散列索引(常规散列映射,如unordered_map)或类型的非唯一散列索引(如unordered_multimap)访问数据使用数据视图。

record_container data;
// .... Fill with data

// Find by ID
auto& id_view = data.get<id_tag>();
auto id_it = id_view.find(15);
if (id_it == id_view.end()) {
    // not found
} else {
    // found
}

您也可以使用这样的容器创建复合键并轻松完成复杂逻辑:

using composite = boost::multi_index::composite_key<
    record,
    boost::multi_index::member<record, int, &record::id>,
    boost::multi_index::member<record, int, &record::type>
>;

修改

如果你不能使用Boost,我有一个MultiIndex的分支,它使用C ++ 11的功能,不需要Boost。它完全取决于Brigand的一小部分,一个C ++ 11,模板元编程,仅头文件库。

答案 1 :(得分:0)

您可以使用类和容器及其迭代器。

class DB
{
  private:
    typedef list<Record>::iterator iterator;

    list<Record> records;
    iterator     itForId; 

  public:
    // return iterator of first record with id == parameter
    iterator GetFirstForId(int id); 
    iterator GetNextForId(int id);

    iterator end()   {return records.end();}

};

删除记录会使迭代器混乱,因此最好将记录标记为删除,然后在不迭代容器时标记删除。

class DataRecord : public  Record
{
  bool markedForDeletion;
};