在 C++ 中对大量元素进行分组的最快方法

Posted

技术标签:

【中文标题】在 C++ 中对大量元素进行分组的最快方法【英文标题】:Fastest way to Group a large number of Elements in C++ 【发布时间】:2015-09-02 18:29:37 【问题描述】:

我需要一种方法将大量连接(目前为 300k)快速分组到组中,其中每个组具有允许的最大元素数(当前为 14k),并且同一组中的所有连接不能连接到同一组观点。基本上,每个连接都在两点之间,我需要将它们分组到存储桶中,其中存储桶中的连接不共享一个点。希望这是有道理的。

这是我目前所拥有的,虽然有效,但速度相当慢:

for (size_t i = 0; i < ConnectionGroups.size(); i++)

    auto& group = ConnectionGroups[i];
    if (group.size() < MaxConnectionGroupSize) // Has room for us...
    
        int validGroupIdx = i;
        for (size_t gIdx = 0; gIdx < group.size(); gIdx++)
        
            const auto groupConnection = ConnectionsQuickAccess[group[gIdx]];

            // Are we directly connected to one of the Connections in this group by one degree...
            if (Connection.Point1 == groupConnection->Point1 || Connection.Point1 == groupConnection->Point2 ||
                Connection.Point2 == groupConnection->Point1 || Connection.Point2 == groupConnection->Point2)
            
                validGroupIdx = -1;
                break; // We are, check the next group
            
        

        if (validGroupIdx != -1)
        
            ConnectionGroups[i].push_back(Connection.Slot);
            Connection.Group = i;
            return;
        
        else
            continue;
    


// All groups are full, create a new group
vector<int> newGroup;
newGroup.push_back(Connection.Slot);
ConnectionGroups.push_back(newGroup);

这段代码需要 29.68 秒才能完成 30 万个连接,有没有更快的方法呢?或者可能有不同的方法?

谢谢!

【问题讨论】:

ConnectionGroupsConnection 的类型。 ConnectionQuickAccess 是什么? ConnectionGroups 是一个vector&lt;vector&lt;int&gt;&gt; int 指的是ConnectionQuickAccess 中的indecis,Connection 仅包含2 个指向它连接的点的指针和其他数据,例如它的组索引而ConnectionQuickAccessvector&lt;Connection*&gt; 充当访问所有已创建连接的快速方法。实际的 Connection 对象在其他地方进行管理。 我认为,如果你有一个容器而不是 vector&lt;Connection*&gt; 来保存按照 Point1 和/或 Point2 排序的数据,如 setmap,那么搜索将采用 4*log(n) 而不是 4*n 并且整个算法将是 n*log(n) 而不是 n^2。 ... 甚至是 C++11 的 unordered_mapundordered_set,其中的搜索复杂度为 O(1)... 【参考方案1】:

似乎发布的代码处理一个连接,即,它被称为n 次,其中n 是连接数。该算法显然是O(n * n):添加新连接所需的时间呈二次方增长——这是您通常不想要的。

除非内存是主要限制,否则我会为每个组简单地存储一个包含所有现有端点的哈希并检查它,即类似于

for (std:size_t i(0); i != ConnectionGroups.size(); ++i) 
    if (ConnectionGroups[i].size () < MaxConnectionGroupSize)
        && !ConnectionGroups[i].usesEndPoint(Connection.Point1)
        && !ConnectionGroups[i].usesEndPoint(Connection.Point2)) 
        ConnectionGroups[i].addEndPoint(Connection.Point1);
        ConnectionGroups[i].addEndPoint(Connection.Point2);
        ConnectionGroups[i].addConnection(Connection);
    

显然,ConnectionGroups[i] 将是连接和使用相应函数访问的端点哈希的组合。

【讨论】:

您能否详细说明“包含所有现有端点的哈希”位?您建议如何实施? @NIZGTR:因为密钥的存在是相关的,所以std::unordered_set&lt;EndPoint&gt; 就可以了。如果端点的唯一性被用于某些好处,那么您实际上可能希望将信息与端点相关联,即,您可以将std::unordered_map&lt;EndPoint, Information&gt; 与任何方便的信息一起使用。

以上是关于在 C++ 中对大量元素进行分组的最快方法的主要内容,如果未能解决你的问题,请参考以下文章

从大表的子集中对随机行进行最快查询 - postgresql

使用 Scala 根据 RDD 中的多个键列对值进行分组的最快方法是啥? [复制]

从 C++ 中的字节数组中提取非零索引的最快方法是啥

R中的性能:对矩阵中的行元素进行排序的最快方法是啥?

寻找对包含 C++ 中三个不同值的 2000 个项目的列表进行排序的最快方法

查找数组的所有元素是不是不同的最快方法?