如何定義這種二維點的小於運算?

struct MyPoint
{
int x; int y;
friend bool operator&<(const MyPoint a, const MyPoint b); }

現在因為set或者map容器只能重寫小於運算,但是要讓這個小於運算滿足下面的等於運算(==相當於!(a&bool operator==(const MyPoint b)
{
if ((x == b.xy == b.y) || (x == b.yy == b.x))
{
return true;
}
else
{
return false;
}
}

但是要如何寫這個小於運算呢,我想了一下這樣寫,但是是有問題的,求正確做法,

friend bool operator &<(const MyPoint a, const MyPoint b) { return (a.x*a.x + a.y*a.y) &< (b.x*b.x + b.y*b.y); }

上面的當Point(0,5)和Point(3,4)判斷相等,不是我想要的結果。

根據靈劍的回答精簡一下要求:就是要重寫&<運算使得,==相等的條件是自己跟自己相等,或自己跟自己關於x = y的鏡像相等。


相等的條件是自己跟自己相等,自己跟自己關於x = y的鏡像相等,這還是蠻奇怪的一個特性的,一般來說可以首先簡單按照x和y的大小關係歸一化成x &< y,這樣後面應該能簡單一些。比較的時候也可以用這種思路,先歸一化,然後分別比較,比較的規則可以是多種多樣的,取決於你的需求。

bool operator&<(const MyPoint a, const MyPoint b){ int x1 = a.x, x2 = b.x, y1 = a.y, y2 = b.y; int t; if(x1 &> y1){
t = x1; x1 = y1; y1 = t;
}
if(x2 &> y2){
t = x2; x2 = y2; y2 = t;
}
return (x1 &< x2) || (x1 == x2 y1 &< y2); }

除了比較大小然後交換以外,也可以計算x + y和|x - y|,也能實現歸一化,它的好處是相當於將坐標旋轉45°,以x = y為一個軸,x = -y為另一個軸,比較的結果是先按到對稱軸順序再按到原點順序(或者反過來)。

如果希望保持先按到原點的距離比較呢?可以這麼寫:

bool operator&<(const MyPoint a, const MyPoint b){ int r1 = a.x * a.x + a.y * a.y, r2 = b.x * b.x + b.y * b.y; return (r1 &< r2) || (r1 == r2 a.x + a.y &< b.x + b.y); }

先按距離比較,距離相等的時候按x + y比較。x + y是向量(x,y)和向量(1,1)的內積,在向量模相等的時候它代表跟y = x成的角的餘弦值,越靠近(1,1)的方向越大,越靠近(-1,-1)的方向越小,而且最好的一點是它對於(x,y)和(y,x)是對稱的,滿足你的相等的條件。


如果覺得求模不夠,那就再比較一下幅角。


return make_pair(a.x, a.y) &< make_pair(b.x, b.y);

等價於

return a.x &< b.x || (a.x == b.x a.y &< b.y);

===== 看錯需求的分割線 =====

先定義 normalize() 成員函數。

std::pair& MyPoint::normalize() const

{

return x &< y ? make_pair(x, y) : make_pair(y, x);

}

然後

return a.normalize() &< b.normalize();

即可。


隨便定義一個(正確的)順序就能保證滿足你要的性質,比如說先比較第一個分量,相同的情況下比較第二個分量


一維下越小的數是離原點越進的書,擴展到二維有什麼不同?

a<b Leftrightarrow sqrt{(a.x)^2+(a.y)^2} < sqrt{(b.x)^2+(b.y)^2}

應該就可以了吧。


推薦閱讀:

C++ 這門語言的優點體現在哪裡?
最近看到陳碩的一本書提了一個問題,「編譯器如何處理inline函數中的static變數?」
C++怎樣讀取文件才有最快的速度?
Mac系統下最好用的C++ IDE是XCode嗎 ?
關於鏈表的問題?

TAG:演算法 | 數學 | 編程 | C |