Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;STL";“关联集/映射”; 我正在寻找一种特殊的SET/MAP的名称,希望有一些现有的代码,如C++ STL。_C++_Algorithm_Stl_Map_Set - Fatal编程技术网

C++;STL";“关联集/映射”; 我正在寻找一种特殊的SET/MAP的名称,希望有一些现有的代码,如C++ STL。

C++;STL";“关联集/映射”; 我正在寻找一种特殊的SET/MAP的名称,希望有一些现有的代码,如C++ STL。,c++,algorithm,stl,map,set,C++,Algorithm,Stl,Map,Set,调用集合A 我想运行以下命令: A.associate(3,5) A.associate(3,6) A.associate(6,8) A.associate(8,10) A.associate(4,9) 然后能够提出以下问题,并收到指示的答案: A.is_associated(3,5) -> True A.is_associated(5,10) -> True A.is_associated(10,3) -> True A.is_associated(4,10) ->

调用集合
A

我想运行以下命令:

A.associate(3,5)
A.associate(3,6)
A.associate(6,8)
A.associate(8,10)
A.associate(4,9)
然后能够提出以下问题,并收到指示的答案:

A.is_associated(3,5)  -> True
A.is_associated(5,10) -> True
A.is_associated(10,3) -> True
A.is_associated(4,10) -> False
你知道这种构造/集合的名称吗


您知道是否存在现有的C/C++实现吗?

一般来说,我认为此数据结构是一个图形:即,在您的情况下,使用整数标识的一组节点,以及可能是有向节点对的一组边。根据您的具体需要,有许多方法来表示和绘制图形。Boost有许多典型的图形数据结构,以及一系列在其上运行的算法


根据注释中的一些说明:
是关联的()
操作是无向图中的路径搜索。根据图形的需要,可以添加edge来表示数据结构,以便
与之关联()
是常数时间,而插入的成本是线性时间。

编辑:如果您想执行额外的步骤,您应该考虑有效地实现

不幸的是,我看到的唯一明智的方法是在
std::set
上创建一个
std::map
——每次插入时都需要检查这两个元素是否在不同的子集中——如果是,就合并它们

因此外部集合存储所有元素并将它们指向它们所属的集合

现在,如果添加新关联:

  • 检查A和B属于哪些集合
  • 如果两者都不属于任何集合,则创建一个新集合并将两个值映射到该集合(结束)
  • 如果一个属于某个集合,而另一个不属于某个集合,则将另一个放入第一个集合并映射到该集合(结束)
  • 如果两者都属于不同的集合,则合并集合并相应地更新元素映射
  • 现在is_关联函数非常快——只需检查这两个元素是否属于同一个集合

    英文:

    typedef std::map< int, std::set< int >& > assoc_set; // note that you need to 
                     // store the sets somewhere else, maybe in another set
    
    typedef std::map&>assoc_set;//请注意,您需要
    //把电视机放在别的地方,也许是另一台
    
    可能是这样的:

    class assoc_set
    {
        typedef std::set< int > int_set;
        typedef std::set< int_set > int_set_set;
        typedef std::map< int, int_set_set::iterator > set_map;
    public:
        void associate( int a, int b )
        {
            set_set_map::iterator ia = iss.find( a );
            set_set_map::iterator ib = iss.find( b );
            if ( ia == set_set_map::end() )
            {
                if ( ib == set_set_map::end() )
                {
                    // create new
                    int_set ab;
                    ab.insert(a);
                    ab.insert(b);
                    int_set_set::iterator r = iss.insert( ab ).second;
                    smap[a] = r;
                    smap[b] = r;
                }
                else
                {
                    // add to a
                    smap[a] = ib;
                    ib->insert( a );
                }
            }
            else
            {
                if ( ib == set_set_map::end() )
                {
                    // add to b
                    smap[b] = ia;
                    ia->insert( b );
                }
                else
                {
                    // merge
                    ia->insert( ib->begin(), ib->end() );
                    // this could be done better
                    for ( int_set::iterator i = it->begin(); i != it->end(); ++i )
                    {
                        smap[*i] = ia;
                    }
    
                }
    
            }
    
    
        }
    
        bool is_associated( int a, int b )
        {
            set_set_map::iterator ia = iss.find( a );
            set_set_map::iterator ib = iss.find( b );
    
            return ia != set_set_map::end() && ia = ib;
        }
    
    private:
        int_set_set iss;
        set_map smap;
    }
    
    类关联集合 { typedef std::setint\u set; typedef std::setint_set; typedef std::mapset_map; 公众: 无效关联(内部a、内部b) { set_set_map::迭代器ia=iss.find(a); set_set_map::迭代器ib=iss.find(b); 如果(ia==set\u set\u map::end()) { if(ib==set\u set\u map::end()) { //创造新的 int_集ab; ab.插入(a); ab.插入(b); 迭代器r=iss.insert(ab).second; smap[a]=r; smap[b]=r; } 其他的 { //添加到 smap[a]=ib; ib->插入(a); } } 其他的 { if(ib==set\u set\u map::end()) { //加上 smap[b]=ia; ia->插入(b); } 其他的 { //合并 ia->insert(ib->begin(),ib->end()); //这可以做得更好 对于(int_set::iterator i=it->begin();i!=it->end();++i) { smap[*i]=ia; } } } } 布尔值是关联的(整数a,整数b) { set_set_map::迭代器ia=iss.find(a); set_set_map::迭代器ib=iss.find(b); 返回ia!=set\u set\u map::end()&&ia=ib; } 私人: 国际空间站; 设置地图smap; } 将会有错误和bug,我只有记事本可用(而且在这上面花费了太多时间)

    添加是
    O(n)
    (但可以通过使用额外的间接层(并摆脱愚蠢的映射循环)减少为
    O(log(n))
    。查询是
    O(log(n))


    使用
    unordered\u set/unordered\u map
    您可能会将两者都减少到
    O(1)
    摊销。

    为什么
    A.is\u关联(5,10)
    true?你能更详细地解释一下关联逻辑吗?顺序是
    5->3->6->8->10
    。似乎没有人理解这个问题:/Ah,所以这是一个双向关联,人们可以根据需要遵循链。是的,我会称之为无向图。我将在将来删除我的答案。OP请更仔细地解释您的要求。@PlatinumAzure,我觉得问题很清楚,没有假设要提出一个潜在的结构,也没有可能对答案产生偏见。如果您正在为此制定一个答案,我深表歉意-感谢您的帮助。如果您想要快速、轻量的施工,这个解决方案很好,但您愿意接受慢速查询。如果您想要快速查询(以较慢的构造和更多的空间需求为代价)你最好使用集合地图。@KornelKisielewicz你可以这样做:如果你想有很多更改和很少的查询,你每次都要进行路径搜索。如果你有很多查询和很少的更改,你可以在更改后设置图形:有很多方法来表示根据特定新闻定制的图形。事实上,集合地图同构于gr想一想,这不是一个图,而是一个不相交的集合。是的,可能是有用的东西。我倾向于认为这是一个使用的图算法,例如在所有对最短路径中。