set::find 找到一个不存在的元素
set::find finds an element that does not exist
我有以下 Edge
class:
class Edge {
public:
int src, dest;
bool operator== (const Edge &edge) const {
return ((src == edge.src) && (dest == edge.dest)) || ((src == edge.dest) && (dest == edge.src));
}
bool operator<(const Edge& edge) const {
return !(((src == edge.src) && (dest == edge.dest)) || ((src == edge.dest) && (dest == edge.src)));
}
Edge(int src, int dest) {
this->src = src;
this->dest = dest;
}
};
重写 <
运算符的要点是当我尝试 find
集合中的一条边 Edge(0, 1)
应该等于 Edge(1, 0)
时。但是,以下测试代码无法做到这一点并且 std::find
returns 甚至不存在的边缘:
Edge edge(0, 3);
set<Edge> test;
test.insert(Edge(3, 1));
test.insert(Edge(3, 0));
auto a = test.find(edge);
cout << a->src << " " << a->dest << endl;
这将奇怪地打印出 2 0
。我不明白为什么,我是 C++ 的新手,感谢任何帮助。
您目前没有 std::set
的有效 Compare,因此您的程序有未定义的行为。
这是一个与您的==
兼容的
bool operator<(const Edge& edge) const {
return std::minmax(src, dest) < std::minmax(edge.src, edge.dest);
}
这也可以用来简化您的 ==
bool operator==(const Edge& edge) const {
return std::minmax(src, dest) == std::minmax(edge.src, edge.dest);
}
您的代码中有两个问题。
首先,你不检查test.find()
是否是returns一条有效边;请注意 find
returns end()
如果没有找到元素。
其次,您的 <
-operator 没有实现严格的排序,它实际上只是定义了一个 !=
。为了克服这个问题,我将对每条边进行归一化,以便始终将较低的节点视为起点;然后根据起始节点决定,只有它们相等,才考虑目的节点:
class Edge {
public:
int src, dest;
bool operator== (const Edge &edge) const {
return ((src == edge.src) && (dest == edge.dest)) || ((src == edge.dest) && (dest == edge.src));
}
bool operator<(const Edge& edge) const {
// return !(((src == edge.src) && (dest == edge.dest)) || ((src == edge.dest) && (dest == edge.src)));
int thisSrc = std::min(src,dest);
int thisDest = std::max(src,dest);
int eSrc = std::min(edge.src,edge.dest);
int eDest = std::max(edge.src,edge.dest);
if (thisSrc < eSrc) {
return true;
} else if (thisSrc > eSrc) {
return false;
} else {
return thisDest < eDest;
}
}
Edge(int src, int dest) {
this->src = src;
this->dest = dest;
}
};
#include <set>
int main() {
Edge edge(0, 3);
std::set<Edge> test;
test.insert(Edge(3, 1));
test.insert(Edge(3, 0));
auto a = test.find(edge);
if (a == test.end()) {
std::cout << "edge not found." << std::endl;
} else {
std::cout << a->src << " " << a->dest << std::endl;
}
}
输出:
3 0
我有以下 Edge
class:
class Edge {
public:
int src, dest;
bool operator== (const Edge &edge) const {
return ((src == edge.src) && (dest == edge.dest)) || ((src == edge.dest) && (dest == edge.src));
}
bool operator<(const Edge& edge) const {
return !(((src == edge.src) && (dest == edge.dest)) || ((src == edge.dest) && (dest == edge.src)));
}
Edge(int src, int dest) {
this->src = src;
this->dest = dest;
}
};
重写 <
运算符的要点是当我尝试 find
集合中的一条边 Edge(0, 1)
应该等于 Edge(1, 0)
时。但是,以下测试代码无法做到这一点并且 std::find
returns 甚至不存在的边缘:
Edge edge(0, 3);
set<Edge> test;
test.insert(Edge(3, 1));
test.insert(Edge(3, 0));
auto a = test.find(edge);
cout << a->src << " " << a->dest << endl;
这将奇怪地打印出 2 0
。我不明白为什么,我是 C++ 的新手,感谢任何帮助。
您目前没有 std::set
的有效 Compare,因此您的程序有未定义的行为。
这是一个与您的==
bool operator<(const Edge& edge) const {
return std::minmax(src, dest) < std::minmax(edge.src, edge.dest);
}
这也可以用来简化您的 ==
bool operator==(const Edge& edge) const {
return std::minmax(src, dest) == std::minmax(edge.src, edge.dest);
}
您的代码中有两个问题。
首先,你不检查test.find()
是否是returns一条有效边;请注意 find
returns end()
如果没有找到元素。
其次,您的 <
-operator 没有实现严格的排序,它实际上只是定义了一个 !=
。为了克服这个问题,我将对每条边进行归一化,以便始终将较低的节点视为起点;然后根据起始节点决定,只有它们相等,才考虑目的节点:
class Edge {
public:
int src, dest;
bool operator== (const Edge &edge) const {
return ((src == edge.src) && (dest == edge.dest)) || ((src == edge.dest) && (dest == edge.src));
}
bool operator<(const Edge& edge) const {
// return !(((src == edge.src) && (dest == edge.dest)) || ((src == edge.dest) && (dest == edge.src)));
int thisSrc = std::min(src,dest);
int thisDest = std::max(src,dest);
int eSrc = std::min(edge.src,edge.dest);
int eDest = std::max(edge.src,edge.dest);
if (thisSrc < eSrc) {
return true;
} else if (thisSrc > eSrc) {
return false;
} else {
return thisDest < eDest;
}
}
Edge(int src, int dest) {
this->src = src;
this->dest = dest;
}
};
#include <set>
int main() {
Edge edge(0, 3);
std::set<Edge> test;
test.insert(Edge(3, 1));
test.insert(Edge(3, 0));
auto a = test.find(edge);
if (a == test.end()) {
std::cout << "edge not found." << std::endl;
} else {
std::cout << a->src << " " << a->dest << std::endl;
}
}
输出:
3 0