【问题标题】:C++ set of struct fails to find/erase by elementC++ 结构集无法按元素查找/擦除
【发布时间】:2019-04-02 06:17:51
【问题描述】:

如下图,y轴区间(即垂直)的集合需要满足两个要求:

1) 它从下到上对所有区间进行排序;

2) 如果新间隔与集合中的任何间隔重叠,则返回插入失败。这类似于 STL set<int> 在插入重复 int 时返回 pair.second == false

我的猜测是自定义比较功能cmp_set导致查找/擦除失败的错误,并且间隔的顺序是降序(应该是升序?)。由于 STL 集依赖于二分查找来查找区间,因此它失败了。

如何解决这个问题?问题是比较函数cmp_set 应该处理上述两个要求 1) 和 2),但返回 int 值作为 -1/1/0 似乎不起作用。将其更改为布尔比较函数仅返回真/假,无法检测重叠间隔。

#include <iostream>
#include <string>
#include <set>

using namespace std;

struct Interval {
    int down;
    int up; 

    Interval(int d, int u) {
        down = d;                        
        up = u;
    }   

    bool operator==(const Interval& other) {
        return down == other.down && up == other.up;
    }   
};

auto cmp_set = [](const Interval& a, const Interval& b) {
    // if (a.up <= b.down) {//a's up is below b's down
    //     return -1;  //sort a before b, like a < b 
    // } else if (a.down >= b.up) {//a's down is above b's up
    //     return 1; //sort a after b, like a > b 
    // } else {
    //     return 0; //overlap. Very similar to the Interval Overlap
    // }
    if (max(a.down, b.down) < min(a.up, b.up)) return 0; //overlap of intervals
    else { //sort the two intervals 
        if(a.up <= b.down) return -1; 
        else return 1;
    }   
};        

void print(set<Interval, decltype(cmp_set)>& s) {
    for (auto it = s.begin(); it != s.end(); it++) {
        cout << it->down << "->" << it->up << ", ";
    }                                
    cout << endl;
}


int main()
{
    set<Interval, decltype(cmp_set)> s(cmp_set);


    s.insert(Interval{1, 3});
    s.insert(Interval{3, 4});
    print(s); //3->4, 1->3, 

    auto iter = s.find(Interval{3, 4});
    if (iter == s.end()) cout << "not find" << endl; //not find

    s.erase(Interval{3, 4});  //fail to remove the Interval
    print(s); //still contains 3->4, 1->3, 

    return 0;
}

【问题讨论】:

  • 您的比较不正确。它必须是strict-weak-order-ing。此外,您的比较应该返回 truefalse,而不是 0、-1 或 1。也许您将 C++ 与另一种计算机语言混淆了?
  • @PaulMcKenzie 非常感谢您的快速回复!是的,它在 Java 中工作。你能帮我修复这个错误吗?
  • 好吧,这就解释了——在编写 C++ 代码时,不要不要使用其他计算机语言作为模型。最重要的是——如果在顺序方面ab 之前,则需要返回true,否则返回false。 0、1、-1 的东西,别管它——它不适合这种情况。
  • 知道了。但是,在 C++ 集合的一个比较函数中,如何同时满足 1) 和 2) 的要求?好像不太可能,如果自定义比较函数只能处理排序不能进行重叠检测,那么插入如何处理呢。
  • 那么您使用的数据结构不符合您的需求。严格弱排序是std::set 确定项目放置位置的方式。要么您必须以某种方式编写代码以适应该范例,要么使用不同的数据结构。另请注意,std::set 在任何情况下都不会使用==,因此编写operator == 会导致“无操作”。

标签: c++ set


【解决方案1】:

如果我正确理解您的比较,对于您需要的设置:

auto cmp_set = [](const Interval& a, const Interval& b) { 
    return a.down >= b.up; 
}

意思是如果集合中a在b之前,a将在b结束之后开始。

当 !(a

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-30
    • 1970-01-01
    • 2011-06-09
    • 2020-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多