C++多集与结构只擦除一个,快速(过载?

C++ multiset with struct erase only one, fast (overload?)

本文关键字:一个 快速 过载 结构 C++ 擦除      更新时间:2023-10-16
struct node {
    int idx;    // each node have a unique index
    int value;  // different nodes can have same value
}
struct node_help {
    bool operator()(const node &a, const node &b) const    
    {
        return a.value < b.value;
    }
}
std::multiset<node, node_help> Nodes;

目前为止,一切都好。现在我想从多集中擦除特定节点。当我使用它时:

Nodes.erase(node (x, y));

每个值为 y 的节点都会被删除,但我只希望删除值为 y 索引 x 的节点。

我通过手动执行此操作解决了这个问题:

for (std::multiset<node, node_comp>::iterator iter = Nodes.begin(); iter != Nodes.end(); iter++) {
    node actual_node = *iter;
    if (actual_node.idx == to_delete.idx && actual_node.value == to_delete.value) {
        Nodes.erase(iter);
    }
    return;
}

但这似乎表现不佳。我有数百万个节点,我需要我能得到的每一个加速。:)有什么想法吗?

好吧,一切都很好。我只是忘了在注销时取下线路。因此,在每次更改集后,都会创建一个日志并将其直接保存到磁盘中。注释掉这一点将时间从 50 秒减少到 0,0x 秒。足够快。:)但无论如何,所有的回应都是如此。

struct node_help {
    bool operator()(const node &a, const node &b) const    
    {
        return a.value <= b.value; // changes the equality check
    }
}

如果您有 C++11,您可以按如下方式定义 lambda 并使其成为更好的代码。否则,您可能需要使用函数对象来代替 lambda。

std::remove(std::begin(Nodes), std::end(Nodes),
             [&to_delete]( struct node & x ) 
             {
                           return ( x.idx == to_delete.idx && 
                            x.value == to_delete.value);
               }

请注意,要使用 std::remove(),您必须包含算法头文件:

#include<algorithm>

您可以以某种方式获得等于 node (x, y) 的元素的迭代器。然后,使用迭代器擦除将仅删除一个元素。

也就是说,使用这样的比较功能,无论如何您都会遇到一些麻烦(就复杂性而言)找到node (x, y),因为具有相同y和不同x的节点无法通过x有效地搜索。

一种解决方案是将比较函数更改为按y排序,然后按x排序,并且可能使用集合而不是多重集合。之后,如果你想要一个具有特定y的元素,你可以使用类似 Nodes.lower_bound (node (-INFINITY, y)) 的东西,它具有复杂性 O(log n)。

how about
    std::multiset<node, node_help> Nodes;
    Nodes.insert(node{ 1, 10 });
    Nodes.insert(node{ 2, 1 });
    Nodes.insert(node{ 3, 1 });
    Nodes.insert(node{ 4, 100 });
    cout << "beforen";
    for (const auto& n : Nodes)
    {
        cout << n.idx << " " << n.value << "n";
    }
    auto it = Nodes.find(node{ 0,1 });
    while(it != Nodes.end())
    {
        Nodes.erase(it);
        it = Nodes.find(node{ 0,1 });
    }
    cout << "naftern";
    for (const auto& n : Nodes)
    {
        cout << n.idx << " " << n.value << "n";
    }

您可以通过仅查看y匹配的节点来获得恒定因子加速

auto [first, last] = Nodes.equal_range(to_delete);
auto it = std::find(first, last, to_delete);
if (it != last) {
    Nodes.erase(it);
}

或者没有C++17

auto range = Nodes.equal_range(to_delete);
auto it = std::find(range.first, range.second, to_delete);
if (it != range.second) {
    Nodes.erase(it);
}

使用 C++14,您可以按nodeint搜索节点

struct node {
    int idx;    // each node have a unique index
    int value;  // different nodes can have same value
};
struct node_less {
    using is_transparent = void;
    bool operator()(const node &a, const node &b) const    
    {
        return std::tie(a.value, a.key) < std::tie(b.value, b.key);
    }
    bool operator()(int a, const node &b) const    
    {
        return a < b.value;
    }
    bool operator()(const node &a, int b) const    
    {
        return a.value < b;
    }
};
std::set<node, node_less> Nodes;
Nodes.find(node{ x, y }); // single node
Nodes.equal_range(y); // all nodes that match y
相关文章: