我最近参加了编程比赛。一项任务是关于几何。我发明的解决方案是使用2D向量的容器,其中每个向量都是唯一的。抛出副本的最快容器是std::unordered_set
。但我忘记了如何制作自定义哈希,所以我使用了std::set
:
struct Vector
{
int x;
int y;
bool operator<(const Vector& rhs) const
{
return x < rhs.x && y < rhs.y;
}
}
std::set<Vector> geometry;
当然是错的。 我明白为什么这是错误的。这是比赛中的六项任务之一,时间限制为2小时。所以我假设,这个任务可以在~20分钟内完成。我可以使用std::vector
检查uniquenes,但测试人员有时间限制,而且速度很慢(O(n ^ 2))。
所以我有这些要求:
std::vector
那么,根据所有这些要求,如何以这种方式存储2D矢量?
答案 0 :(得分:3)
我认为你在std::set
中存储(让我说点数)的想法很好并且在实践中运作良好。
但是您在operator<()
的实施中遇到了错误。例如。积分会发生什么
(1, 4)
和(2, 2)
?你的代码会告诉你
(1, 4) >=(2, 2)
和(2, 2) >= (1, 4)
,这是stl
你可以使用std::tie()
自动化这样的同情,如下所示:
struct Vector
{
int x;
int y;
bool operator<(const Vector& rhs) const
{
return std::tie(x, y) < std::tie(rhs.x, rhs.y);
}
};
答案 1 :(得分:3)
正如另一个答案所指出的,理论上你的解决方案是正确的。但是,operator <
不正确。
使用<complex>
的替代方法是使用代表x,y点的std::pair
。 std::pair
包含内置operator <
,因此您需要做的就是在operator <
函数中调用它。
见这里:http://en.cppreference.com/w/cpp/utility/pair
#include <set>
#include <map>
#include <iostream>
struct Vector
{
std::pair<int, int> xy;
Vector(int x_ = 0, int y_ = 0) : xy(std::make_pair(x_, y_)) {}
bool operator<(const Vector& rhs) const
{ return xy < rhs.xy; }
};
std::set<Vector> geometry;
int main()
{
geometry.insert(Vector(1,2));
geometry.insert(Vector(1,5));
geometry.insert(Vector(1, 8));
geometry.insert(Vector(1, 8));
geometry.insert(Vector(1, 8)); // repeated
geometry.insert(Vector(1, 8)); // repeated
geometry.insert(Vector(2, 2));
std::cout << geometry.size();
}
该示例显示只有唯一项存储在集合中,表明std::pair
具有operator <
所需的正确语义。
鉴于此,除非您在Vector
课程中添加其他成员函数,否则您可以简单地完成此操作:
std::set<std::pair<int, int>> geometry;
然后在main
:
int main()
{
geometry.insert(make_pair(1,2));
geometry.insert(make_pair(1, 5));
geometry.insert(make_pair(1, 8));
geometry.insert(make_pair(1, 8));
}
但是,如果您知道pair
代表的内容,并且您打算不将Vector
类扩展为超过x / y值的内容,请执行此操作。
答案 2 :(得分:0)
关于std::set
中的排序的要点是必须存在某种排序,但排序不必具有任何实际意义。这意味着我们可以自由地使用任何顺序,前提是不同的对从不被视为相等。一个简单的方法是:
struct Vector
{
int x;
int y;
bool operator<(const Vector& rhs) const
{
if (x == x.rhs) {
return y < rhs.y;
else {
return x < rhs.x;
}
}
}
std::set<Vector> geometry;
在上面,我们将首先对x进行排序,只有它们相等才会对y进行排序。这将提供stl::set
所需的唯一排序。
答案 3 :(得分:0)
将std::unordered_set
与您选择的哈希一起使用。另外,不要忘记重载operator==
的唯一性。总而言之,
#include <iostream>
#include <unordered_set>
struct Vector
{
int x;
int y;
Vector(int x_, int y_) : x(x_), y(y_) { }
friend bool
operator==(const Vector& lhs, const Vector& rhs)
{ return (lhs.x == rhs.x) && (lhs.y == rhs.y); }
};
struct Hash
{
int operator()(const Vector& v)
const { return (v.x + v.y) % 13; }
//^^^^^
//hasher functions must be const
};
int main()
{
std::unordered_set<Vector, Hash> vectorset;
vectorset.insert(Vector(0, 1)); //unique
vectorset.insert(Vector(2, 1)); //unique
vectorset.insert(Vector(3, 4)); //unqiue
vectorset.insert(Vector(0, 1)); //repeat
vectorset.insert(Vector(2, 1)); //repeat
vectorset.insert(Vector(3, 4)); //repeat
vectorset.insert(Vector(2, 1)); //repeat
vectorset.insert(Vector(9, 4)); //unique
vectorset.insert(Vector(2, 1)); //repeat
std::cout << vectorset.size() << std::endl;
return 0;
}
输出: 4