什么是快速查找最好的c ++ stl容器?

时间:2015-04-02 12:54:04

标签: c++ stl

我搜索一个具有快速查找时间的容器,并且我希望将对象存储在其中,如下所示

class Flow{
const int L3Outside;
const int L4Protocol;
const int L4Oustside;
const int L4Inside;
time_t inOut;
time_t outIn;
}

容器应该只存储唯一的元素但是为了比较两个对象是否相等只是必须比较常量变量。

如果元素已经不在容器中,我尝试插入元素的时间有一半,如果元素已经包含在容器中,我必须找到并访问元素的一半时间。

同样重要的是它们不应该因为散列而发生任何碰撞,或者如果它们是碰撞,我必须能够插入两个元素,并且如果它们不仅等于它们的哈希值,也只找到一个元素。

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

<强> std::multimap

查找: O(log N)加上线性,如果该特定密钥有多个元素。

插入: O(log N)

似乎是最平衡的查找和插入速度,并且可以很好地处理碰撞。

答案 1 :(得分:0)

执行此操作的std ::方法是根据上面的答案 - 将不可变密钥与可变数据分开,这是std::mapstd::unordered_map的目的。

如果由于某些遗留原因而绝对无法执行此操作,则可以使用std::set并提供自定义less仿函数。或者您可以使用std::unordered_set,在这种情况下,您需要提供自定义相等函数对象和自定义哈希对象。

从c ++ 11开始,请注意std::set<>::iterator类型具有const语义(即referent不可变),因此您需要使用const_cast来强制解决问题:

#include <iostream>
#include <set>
#include <tuple>
#include <utility>
#include <ctime>

struct compare_flow_less;

class Flow{
public:
    Flow(int l3o, int l4p, int l4o, int l4i, time_t io = 0, time_t oi = 0)
    : L3Outside { l3o }
    , L4Protocol { l4p }
    , L4Outside { l4o }
    , L4Inside { l4i }
    , inOut { io }
    , outIn { oi }
    {
    }    

    void set_times(time_t t1, time_t t2)
    {
        inOut = t1;
        outIn = t2;
    }

private:
    const int L3Outside;
    const int L4Protocol;
    const int L4Outside;
    const int L4Inside;
    time_t inOut;
    time_t outIn;

    friend compare_flow_less;
};

struct compare_flow_less
{
    bool operator()(const Flow&l, const Flow&r)
    {
        return l.L3Outside < r.L3Outside
        && l.L4Protocol < r.L4Protocol
        && l.L4Outside < r.L4Outside
        && l.L4Inside < r.L4Inside;
    }
};

using FlowSet = std::set<Flow, compare_flow_less>;

using namespace std;

int main()
{
    FlowSet myflows;

    // to insert/overwrite a flow
    time_t t1 = time(nullptr);
    time_t t2 = t1 + 1;

    bool inserted = false;
    FlowSet::iterator insert_position;

    // try to insert a new one
    tie(insert_position, inserted) = myflows.emplace(1,2,3,4,t1,t2);

    // if insertion failed, one already exists so update it
    if (!inserted) {
        const_cast<Flow&>(*insert_position).set_times(t1, t2);
    }

   return 0;
}