C++ 类类型集

C++ 类类型集,c++,stl,C++,Stl,您是否可以编写一个重载函数来从设置中删除数据对象,例如:s.erase(4)Here4可以是值或x或y struct DATA { DATA(int X, int Y):x(X), y(Y){} int x; int y; bool operator < (const DATA &d) const { return x < d.x || (x == d.x && y < d.y); } }; int

您是否可以编写一个重载函数来从设置中删除数据对象,例如:
s.erase(4)
Here
4
可以是值或x或y

struct DATA
{
   DATA(int X, int Y):x(X), y(Y){}
   int x;
   int y;

   bool operator < (const DATA &d) const
   {
       return x < d.x || (x == d.x && y < d.y);
   }
};


int main()
{
   set <DATA> s;

   for (int i = 0; i < 5; i++)
      s.insert(DATA(i, i+5));

   s.erase(0) // remove where x = 0
}
struct数据
{
数据(intx,inty):X(X),Y(Y){
int x;
int-y;
布尔运算符<(常数数据和d)常数
{
返回x
否;您的集合是按X排序的,您也不能按Y排序集合以便按其删除。您需要遍历集合以查找要删除的项目,然后像通常从集合中删除一样删除它们。

否;您的集合是按X排序的,您也不能按Y排序集合以便按其删除。您需要遍历集合以查找要删除的项目,然后像通常从集合中删除一样删除它们。

当然

您可以编写一个函子来搜索x或y为4的集合元素,并删除这些元素。您需要
boost::bind
使绑定更容易:

#include <set>
#include <algorithm>
#include <boost/bind.hpp>

struct Foo {
    int x, y;

    bool operator<(const Foo& rhs) const {
        return (x < rhs.x || (x == rhs.x && y < rhs.y));
    }

    bool hasValue(int v) const {
        return (x == v || y == v);
    }
};

int main()
{
    std::set<Foo> s;
    Foo a = {4,2}; s.insert(a);
    Foo b = {3,4}; s.insert(b);

    std::cout << s.size() << std::endl; // will output: "2"

    std::set<Foo>::iterator it;

    // Search for an element with the given value '4' in either x or y
    // Erase first matching element found, if any
    // (our first element, which has x=4)
    it = std::find_if(s.begin(), s.end(), boost::bind(&Foo::hasValue, _1, 4));
    if (it != s.end())
        s.erase(it);

    std::cout << s.size() << std::endl; // will output: "1"

    // Erase the next one
    // (our second element, which has y=4)
    it = std::find_if(s.begin(), s.end(), boost::bind(&Foo::hasValue, _1, 4));
    if (it != s.end())
        s.erase(it);

    std::cout << s.size() << std::endl; // will output: "0"
}
#包括
#包括
#包括
结构Foo{
int x,y;
布尔运算符当然

您可以编写一个函子来搜索x或y为4的集合元素,并删除这些元素。您需要
boost::bind
使绑定更容易:

#include <set>
#include <algorithm>
#include <boost/bind.hpp>

struct Foo {
    int x, y;

    bool operator<(const Foo& rhs) const {
        return (x < rhs.x || (x == rhs.x && y < rhs.y));
    }

    bool hasValue(int v) const {
        return (x == v || y == v);
    }
};

int main()
{
    std::set<Foo> s;
    Foo a = {4,2}; s.insert(a);
    Foo b = {3,4}; s.insert(b);

    std::cout << s.size() << std::endl; // will output: "2"

    std::set<Foo>::iterator it;

    // Search for an element with the given value '4' in either x or y
    // Erase first matching element found, if any
    // (our first element, which has x=4)
    it = std::find_if(s.begin(), s.end(), boost::bind(&Foo::hasValue, _1, 4));
    if (it != s.end())
        s.erase(it);

    std::cout << s.size() << std::endl; // will output: "1"

    // Erase the next one
    // (our second element, which has y=4)
    it = std::find_if(s.begin(), s.end(), boost::bind(&Foo::hasValue, _1, 4));
    if (it != s.end())
        s.erase(it);

    std::cout << s.size() << std::endl; // will output: "0"
}
#包括
#包括
#包括
结构Foo{
int x,y;
布尔运算符使用

这里有一个。

用法



这里是一个。

当然-您可以修改数据结构以操作较大的整数类型,并使用位移位将一对较小的整数类型打包到中。但是,在更一般的意义上,则不是。有些容器是多索引的,但std::set不是其中之一。

当然-您可以修改数据结构以操作较小的整数类型更大的整数类型,并使用位移位将一对较小的整数类型打包。但是,在更一般的意义上,则不是。有多个索引的容器,但std::set不是其中之一。

关于
std::map
容器如何?您可以使用x或y作为键类型,并将类中的非键值保留为值类型.

关于
std::map
容器如何?您可以使用x或y作为键类型,并将类中的非键值保留为值类型。

您不能简单地重载“操作符==”?您不能简单地重载“操作符==”?不,他的集合是按
x
y
排序的。请查看他的比较器函数。(事实上,“问题”是指他不能有选择地对其中一个进行索引;它们作为一对值紧密相连。)@Tomalak:y是一个辅助键——该集合由x索引,y用于断开联系。你可以查找主键(x),但不能查找辅助键(至少,不能使用单个集合结构)。他将如何使用
std::set
的机制来查找
x
?容器的密钥几乎等同于
std::pair
,而不是
int
@Tomalak:Find Data(WantedXValue,0)和Data(WantedXValue+1,0)(这将为您提供具有该x值的项目范围)在
lg n
时间中。不,他的集合是按
x
y
排序的。请参见他的比较器函数。(事实上,“问题”在于他无法选择性地对其中一个进行索引;它们作为一对值紧密相连。)@Tomalak:y是一个辅助键——集合由x索引,y用于断开连接。您可以查找主键(x),但不能按辅助键查找(至少不能使用单个集合结构)。他将如何使用
std::set
的机制来查找
x
?容器的密钥几乎等同于
std::pair
,而不是
int
@Tomalak:Find Data(WantedXValue,0)和Data(WantedXValue+1,0)(这将为您提供具有该x值的项目范围)在
lg n
time中。是的,你可以对整个过程进行迭代,但你无法获得集合的性能特征(你的搜索和删除需要O(n^2 lg n)时间,而你希望一个集合需要O(lg n)时间)。更好的是,使用一个手写循环,标记你想要删除的所有元素,然后一次性删除它们(如我的回答所示)将总时间降至O(n lg n)。至于失去集合的性能特征,这是OP的固有要求。老实说,在我看来,想要做到这一点首先有点代码味道。我建议在这里使用
std::multimap
。比利,你怎么看?@Tomalak:multimap每个键存储多个项目,而不是多个键per项。@Billy ONeal:对不起,实际上想到的是
boost::bimap
。他想要映射行为,他想在任意一个方向上建立索引。是的,你可以迭代整个过程,但你得不到集合的性能特征(你的搜索和删除需要O(n^2 lg n)时间,而一个集合需要O(lg n)时间)。更好的方法是,使用手写循环标记所有要删除的元素,并一次性删除它们(如我的答案所示),这会将总时间降低到O(n lg n)。至于失去集合的性能特征,这是OP的固有要求。老实说,在我看来,想要做到这一点首先有点代码味道。我建议在这里使用
std::multimap
。比利,你怎么看?@Tomalak:multimap每个键存储多个项目,而不是多个键per项。@Billy ONeal:对不起,实际上想到的是
boost::bimap
。他想要映射行为,他想在任意方向上建立索引。我不确定合并到一个更大的整数类型将如何帮助搜索std::set中的部分值。无论如何,即使这是可能的,我认为你也不应该给初学者关于h的想法如何混淆他们的代码以使其被遗忘…:)我不是真正的s