多个查找集

Multiple lookup set

本文关键字:查找      更新时间:2023-10-16

我需要一个数据结构,但我不确定该选择什么。从根本上说,我的需求与std::set相似,只是我需要同时根据多个不同的比较器对相同的数据进行查找。

现在我决定去一些笨拙 - 一个std::map<float, std::unordered_set<T>>然后是一个std::unordered_map<T, std::unordered_set<T>*>。这应该允许 O(log N) 查找float和 O(1) 查找/删除T

有没有更好的数据结构可以使用?这上面写满了"黑客"。

顺便说一句,这段代码性能相当关键,所以快速的东西将不胜感激。

编辑:我一直在戳boost::multi_index,这是我到目前为止得到的:

boost::multi_index_container<
    NodeType,
    boost::multi_index::indexed_by<
        boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>, decltype(node_comparator)>,
        boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>
    >
> open_set(
    boost::make_tuple(node_comparator)
);

其中node_comparator是in_scope lambda。但是尝试编译它会导致一些光荣的错误。

1>d:backupscodeboost_1_47_0boostmulti_indexdetailnode_type.hpp(56): error C2903: 'node_class' : symbol is neither a class template nor a function template
1>          d:backupscodeboost_1_47_0boostmplaux_preprocessedplainapply_wrap.hpp(49) : see reference to class template instantiation 'boost::multi_index::detail::index_node_applier::apply<IndexSpecifierIterator,Super>' being compiled
1>          with
1>          [
1>              IndexSpecifierIterator=boost::mpl::v_iter<boost::mpl::vector2<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,0>,
1>              Super=boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<NodeType,std::allocator<NodeType>>>
1>          ]
1>          d:backupscodeboost_1_47_0boostmplaux_preprocessedplainbind.hpp(207) : see reference to class template instantiation 'boost::mpl::apply_wrap2<F,T1,T2>' being compiled
1>          with
1>          [
1>              F=boost::multi_index::detail::index_node_applier,
1>              T1=boost::mpl::v_iter<boost::mpl::vector2<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,0>,
1>              T2=boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<NodeType,std::allocator<NodeType>>>
1>          ]
1>          d:backupscodeboost_1_47_0boostmplaux_preprocessedplainapply_wrap.hpp(49) : see reference to class template instantiation 'boost::mpl::bind2<F,T1,T2>::apply<U1,U2>' being compiled
1>          with
1>          [
1>              F=boost::multi_index::detail::index_node_applier,
1>              T1=boost::mpl::_2,
1>              T2=boost::mpl::_1,
1>              U1=boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<NodeType,std::allocator<NodeType>>>,
1>              U2=boost::mpl::v_iter<boost::mpl::vector2<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,0>
1>          ]
1>          d:backupscodeboost_1_47_0boostmplaux_preprocessedplainapply.hpp(63) : see reference to class template instantiation 'boost::mpl::apply_wrap2<F,T1,T2>' being compiled
1>          with
1>          [
1>              F=boost::mpl::bind2<boost::multi_index::detail::index_node_applier,boost::mpl::_2,boost::mpl::_1>,
1>              T1=boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<NodeType,std::allocator<NodeType>>>,
1>              T2=boost::mpl::v_iter<boost::mpl::vector2<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,0>
1>          ]
1>          d:backupscodeboost_1_47_0boostmplaux_preprocessedplainreverse_iter_fold_impl.hpp(82) : see reference to class template instantiation 'boost::mpl::apply2<F,T1,T2>' being compiled
1>          with
1>          [
1>              F=boost::mpl::bind2<boost::multi_index::detail::index_node_applier,boost::mpl::_2,boost::mpl::_1>,
1>              T1=boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<NodeType,std::allocator<NodeType>>>,
1>              T2=boost::mpl::v_iter<boost::mpl::vector2<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,0>
1>          ]
1>          d:backupscodeboost_1_47_0boostmplreverse_iter_fold.hpp(43) : see reference to class template instantiation 'boost::mpl::aux::reverse_iter_fold_impl<N,First,Last,State,BackwardOp,ForwardOp>' being compiled
1>          with
1>          [
1>              N=2,
1>              First=boost::mpl::v_iter<boost::mpl::vector2<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,0>,
1>              Last=boost::mpl::v_iter<boost::mpl::vector2<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,2>,
1>              State=boost::multi_index::detail::index_node_base<NodeType,std::allocator<NodeType>>,
1>              BackwardOp=boost::mpl::bind2<boost::multi_index::detail::index_node_applier,boost::mpl::_2,boost::mpl::_1>,
1>              ForwardOp=boost::mpl::protect<boost::mpl::arg<1>>
1>          ]
1>          d:backupscodeboost_1_47_0boostmulti_indexdetailnode_type.hpp(70) : see reference to class template instantiation 'boost::mpl::reverse_iter_fold<Sequence,State,BackwardOp>' being compiled
1>          with
1>          [
1>              Sequence=boost::multi_index::indexed_by<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,
1>              State=boost::multi_index::detail::index_node_base<NodeType,std::allocator<NodeType>>,
1>              BackwardOp=boost::mpl::bind2<boost::multi_index::detail::index_node_applier,boost::mpl::_2,boost::mpl::_1>
1>          ]
1>          d:backupscodeboost_1_47_0boostmulti_index_container.hpp(75) : see reference to class template instantiation 'boost::multi_index::detail::multi_index_node_type<Value,IndexSpecifierList,Allocator>' being compiled
1>          with
1>          [
1>              Value=NodeType,
1>              IndexSpecifierList=boost::multi_index::indexed_by<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,
1>              Allocator=std::allocator<NodeType>
1>          ]
1>          c:reporenderrendersimsimcontext.cpp(264) : see reference to class template instantiation 'boost::multi_index::multi_index_container<Value,IndexSpecifierList>' being compiled
1>          with
1>          [
1>              Value=NodeType,
1>              IndexSpecifierList=boost::multi_index::indexed_by<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>
1>          ]

这只是第一个;有很多,但我很清楚Visual Studio倾向于让一个错误导致9999999更多。

您可以尝试的一件事是在unordered_set中使用weak_ptr,并为元素使用shared_ptr。销毁元素时,会留下一个 NULL weak_ptr。您需要某种方法来垃圾收集容器中的这些 NULL weak_ptr 条目,但该成本可能很容易摊销。这样,您就完全不需要使用第二个索引。

multi_index是赢家。不幸的是,dirkgently作为评论发布,而不是回答,否则我会接受它。