【问题标题】:Erasing duplicates from nested map (k-core algorithm)从嵌套映射中删除重复项(k-core 算法)
【发布时间】:2021-09-22 17:43:29
【问题描述】:

我正在尝试完成作业并出现错误。 我想要做的是:有一个无序映射,其键包含值作为 unordered_set,其中可能有“可能与无序外部映射的键具有相同名称”的键。

为了特别,我正在尝试实现一个 k 核算法,计数和 k 数字就在那里。我正在尝试删除具有小于 k 大小的 unordered_sets(包含邻居,调用 N)的 unordered_map 键(让我们调用 P)。 但是由于我从P节点中删除了N条目,我还需要从外部映射中找到N条目并找到P并将其删除。

以下代码是我到目前为止想出的(还有更多,但我不想抄袭或任何东西)。在调试过程中,我注意到有点 cout

编辑:我已经根据建议更新了代码,但是有一个新问题:对于 k=1,节点的数量是正确的。但是在 k=2,3,4.. 之后,最外层循环是无限循环的。并且大小保持不变(取出 k=1 的节点后)

while(nodes.size()!=0)
{
    int count = 0;
    while(stillLeft){
        stillLeft = 0;
        it = nodes.begin();
        while(it != nodes.end()){
            
            if(it->second.size()<=k){
                stillLeft = 1;
                ++count;
                for ( innerit = it->second.begin(); innerit != it->second.end();innerit++ ){
                    nodes.find(*innerit)->second.erase(it->first);

                }
                it = nodes.erase(it);
                }
            else{
                ++it;
            }
                                    }
            
            }
        
    
    cout << nodes.size() << endl;
        
    kCoreNumbers.push_back(count);      
    ++k;
}

【问题讨论】:

  • 试过在onlinegdb调试它?
  • 另外,这就是你正在处理的{{1, {1, 2}}, {5, {6, 1, 7}}},所以如果k= 2,你删除节点1,现在你还需要从邻居列表中删除它节点5 改成{5, {6,7} (需要再次删除?
  • @Zoso 是的。我没有尝试过在线调试器,因为我不知道如何使用调试器工具。我只用 cout 线调试。
  • 看起来您正在擦除P 所指的节点。这可能会破坏 for 循环迭代。您应该使用 for 循环(不是基于范围的 for 循环)并手动跟踪 nodes 中的迭代器。这也可以避免重新查找要擦除的迭代器,因为您已经拥有它(并且在您擦除它时可以正确更新它)。
  • 我已经更新了代码但是有一个新的错误,我找不到它发生的原因。不过谢谢你的建议,它工作得更好@1201ProgramAlarm

标签: c++ cluster-analysis unordered-map erase unordered-set


【解决方案1】:

您不需要循环直到while(nodes.size()!=0) 即直到nodes 为空。运行k-core 算法后,您可能会留下顶点度数大于k 的节点。您只需要循环直到没有度数小于k 的节点。

您的初始代码方向正确,但存在在遍历地图时删除地图中的节点的问题。我通过在迭代图形时将要删除的顶点添加到向量中来解决它,然后在每次图形遍历之后删除所有要删除的节点。这是我的代码版本,基于您的代码更改了一些变量名称以反映它们的含义:

void runKCore(size_t k) {
    bool nodesDeleted;
    do {
        // To keep track of how many times the loop needs to run
        nodesDeleted = false;
        // To keep track of the nodes to be deleted after one pass
        std::vector<int> markDeleted;
        for(auto const& node: graph) {
            auto vertex = node.first;
            auto const& neighbours = node.second;
            // Pick vertex if it has less than k neighbours
            if(neighbours.size() < k) {
                for(auto neighbour: neighbours) {
                    // Get the neighbour's list of vertices
                    auto& neighBoursEdges = graph.at(neighbour);
                    // Remove vertex from this list
                    neighBoursEdges.erase(vertex);
                }
                // Mark this node as deleted
                markDeleted.push_back(vertex);
            }
        }
        // Update nodesDeleted if any nodes were marked for deletion
        nodesDeleted = markDeleted.size() > 0;
        for(auto node: markDeleted) {
            // Erase the node and it's neighbours
            graph.erase(node);
        }
    }while(nodesDeleted);
}

Here是完整的程序。

对于初始图

转换为初始图

8: 6 5 
7: 6 3 4 
6: 7 3 8 5 4 2 
5: 8 6 2 1 
4: 7 3 6 2 
3: 7 6 4 2 
2: 6 3 4 5 1 0 
1: 5 2 0 
0: 2 1 

运行k-core算法后程序的输出k = 3输出为:

7: 6 3 4 
6: 7 3 4 2 
4: 7 3 6 2 
3: 7 6 4 2 
2: 6 3 4 

【讨论】:

    猜你喜欢
    • 2016-10-19
    • 2021-03-22
    • 2021-11-27
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    • 2020-06-26
    • 1970-01-01
    • 2018-04-25
    相关资源
    最近更新 更多