我正在尝试使用std::set
,我将抛出一堆边,并且只保留唯一的边。
Edge
是两个(整数索引)节点之间的一条线。边(1,2)==(2,1)
,因为这些边是无向的。
//??
的部分,行为不符合我的预期。
运行此代码的结果只保留2个边,(1,2)和(4,8)。 (2,1)被集合丢弃,但它不应该,除非我激活//|| ( A==o.B && B==o.A )
中注释掉的operator==
部分!这里发生了什么?
这个set<Edge>
实施让我感到很兴奋。
#include <stdio.h>
#include <set>
using namespace std ;
struct Edge
{
int A,B ;
Edge( int iA, int iB ) : A(iA), B(iB) {}
bool operator==( const Edge & o ) const {
//??
return ( A==o.A && B==o.B ) ;//|| ( A==o.B && B==o.A ) ;
}
bool operator<( const Edge& o ) const {//MUST BE CONST
return A < o.A && B < o.B ;
}
void print() const { printf( "( %d, %d )", A,B ) ; }
void compare( const Edge& o ) const {
print() ;
if( *this==o ) printf( "==" ) ;
else printf( "!=" ) ;
o.print() ;
puts("");
}
} ;
int main()
{
Edge e1( 1, 2 ) ;
Edge e2( 1, 2 ) ;
Edge e3( 2, 1 ) ;
Edge e4( 4, 8 ) ;
e1.compare( e2 ) ;
e1.compare( e3 ) ;
e1.compare( e4 ) ;
set<Edge> edges ;
edges.insert( e1 ) ;
edges.insert( e2 ) ;
edges.insert( e3 ) ;
edges.insert( e4 ) ;
printf( "%d edges\n", edges.size() ) ;
for( auto edge : edges )
{
edge.print();
}
}
答案 0 :(得分:5)
C ++ set与==
运算符无关,与<
运算符无关。您的<
运算符会出现问题:如果您希望确保(1,2)
等于(2,1)
,则应更改<
的执行情况像这样:
bool operator<( const Edge& o ) const {
int myMin = min(A, B);
int myMax = max(A, B);
int hisMin = min(o.A, o.B);
int hisMax = max(o.A, o.B);
return myMin < hisMin || ( myMin == hisMin && myMax < hisMax );
}
这个实现的作用是构造一个边缘的规范表示,其中{A,B}
中较小的一个变为“规范A
”,而较大的一个变为“规范B
”。当以规范形式比较边缘时,(1,2)
和(2,1)
的相等性可以暗示来自(1,2) < (2,1)
和(2,1) < (1,2)
的评估到false
。
答案 1 :(得分:3)
我认为您的operator<
错误,e3<e2
和e2<e3
都是错误的。
也许你想要这样的东西:
return A < o.A || ((A == o.A) && (B < o.B)) ;
答案 2 :(得分:2)
我建议您更改Edge()构造函数,以确保始终初始化A和B,使A<=B
(如果边可以指向其原始节点)或A<B
(如果不是) ,并放弃在operator ==实现中有额外的逻辑。这对我来说似乎不那么“前卫”了。
答案 3 :(得分:-1)
您的比较应该是
return (A == o.A && B == o.B) || (B == o.A && A == o.B);