【问题标题】:Order: An Analysis on Point Sorting顺序:点排序分析
【发布时间】:2013-08-13 05:39:57
【问题描述】:

所以我为自己制作了一个点打印类,它应该让用户输入 2 元组;即 x 和 y,然后以 ^order,^ 将它们打印回用户,其中 order 表示 p1=(x,y)

#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <algorithm>

using namespace std;

class Point2D {
public:
    Point2D();
    Point2D(double a, double b);

    double getx();
    double gety();

    void setx(double a);
    void sety(double b);

    virtual void print();
    virtual void print(int a);

    double angle();

private:
    double x;
    double y;
};

bool operator<( Point2D a , Point2D b );

int main() {

    double my_x=-999;
    double my_y=-999;
    string my_color;
    double my_weight;
    vector<Point2D*> points;

    cout << "Welcome to Point Printer! Please insert the x-and y-coordinates for your points and I will print them in sorted order! Just one rule, the point (0,0) is reserved as the terminating point, so when you are done enter (0,0).\n";

    while(true)
    {
        cout << "x = ";
        cin>>my_x;
        cout << "y = ";
        cin>>my_y;
        if((my_x == 0)&&(my_y==0))
        {
            break;
        }
        points.push_back(new Point2D(my_x, my_y));
    }
    sort(points.begin(), points.end());

    cout << "\n\n";
    cout << "Your points are\n\n";

    for(int i=0;i<points.size();i++)
    {
        cout<<i+1<<": ";
        (*points[i]).print(); cout<<endl; // this is the printing gadget
    }
    for(int i=0; i<points.size(); i++) 
    {
        delete points[i];
    }
    cout << endl << endl;

    return 0;

}

double Point2D::angle()
{
    double Angle = atan2(y,x);
    if(Angle < 0)
    {
        return Angle + 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679;
    }
    return Angle;
}

bool operator< (Point2D a, Point2D b)
{
    if (a.getx()*a.getx()+a.gety()*a.gety() < b.getx()*b.getx()+b.gety()*b.gety())
    {
        return true;
    }
    else if (a.getx()*a.getx()+a.gety()*a.gety() > b.getx()*b.getx()+b.gety()*b.gety())
    {
        return false;
    }
    if (a.getx()*a.getx()+a.gety()*a.gety() ==b.getx()*b.getx()+b.gety()*b.gety())
    {
        if (a.angle() < b.angle())
        {
            return true;
        }
        else if (a.angle() > b.angle())
        {
            return false;
        }
    }
    return true;
}

Point2D::Point2D() { x = 0; y = 0; return;}

Point2D::Point2D(double a, double b) { x = a; y = b; return;}

double Point2D::getx() { return x;}
double Point2D::gety() { return y;}

void Point2D::setx(double a) { x = a; return; }
void Point2D::sety(double b) { y = b; return; }

void Point2D::print() {
    cout<<"("<<x<<","<<y<<")";
    return;
}

void Point2D::print(int a) {
    print(); cout<<endl;
}

我遇到的问题是以下之一:

排序

角度()

算子

完全不同的东西......

特别是以下几点:

x = 1
y = 2
x = 2
y = 3
x = 1.1
y = 2.2
x = -10
y = 10
x = -5
y = -3
x = -5
y = 3
x = 5
y = -3
x = 5
y = 3
x = 0
y = 0

没有按正确的顺序排序。

任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 如果您对我的代码有任何疑问,请询问。
  • 你有什么“麻烦”?
  • 您的比较功能非常多余。您进行相同的两次计算,每次计算 3 次。这就是变量的用途。
  • 我遇到的“麻烦”是我应该在帖子中包含的点 - 现在添加这些点 - 没有按照上面提到的“正确”排序方案。
  • 在您的机器上试用该程序,并输入帖子中提到的数据点。我应该得到1: (1,2) 2: (1.1,2.2) 3: (2,3) 4: (5,3) 5: (-5,3) 6: (-5,-3) 7: (5,-3) 8: (-10,10)

标签: c++ class operator-overloading


【解决方案1】:

问题(或其中一个问题)是比较函数中的最后一条语句。

return true;

看看这个块:

if (a.getx()*a.getx()+a.gety()*a.gety() ==b.getx()*b.getx()+b.gety()*b.gety())
{
    if (a.angle() < b.angle())
    {
        return true;
    }
    else if (a.angle() > b.angle())
    {
        return false;
    }
}

首先,如果我们已经到了这一点,我们已经确定ab(x*x + y*y) 计算是相等的。现在让我们假设角度也相等。发生什么了?第一个测试失败,因为a.angle() 不小于b.angle()。然后第二个测试失败,因为a.angle() 不大于b.angle()。然后你返回真。换句话说,你是说a 小于b 是真的,尽管从所有权利来说,它们应该被认为是相等的,所以你应该返回false。您可以return a.angle() &lt; b.angle();,而不是对角度进行多次测试,这应该可以解决问题。通过一些额外的简化,您的函数应如下所示:

bool operator<(Point2d a, Point2d b)
{
    double A = a.getx()*a.getx()+a.gety()*a.gety();
    double B = b.getx()*b.getx()+b.gety()*b.gety();

    if (A < B) return true;
    if (A > B) return false;
    return a.angle() < b.angle();
}

【讨论】:

  • 嗯...很好。谢谢你,本杰明林德利。
【解决方案2】:

问题可能在于您正在存储和排序指针,而不是对象。积分不会与您的运营商进行比较,而是与他们的地址进行比较。尝试将点更改为vector&lt;Point2d&gt;

【讨论】:

    【解决方案3】:

    首先使用(如果您只是打算对 2D 点进行排序):

    编辑:参见下面的 Benjamin Lindley cmets。)

    bool operator < ( Point2D a,  Point2D b)
    {
        return a.getx() < b.getx() || 
              (a.getx()==b.getx() && a.gety()< b.gety() );
    }
    

    另一件事如果在operator &lt; ( Point2D a, Point2D b) 中使用std::cout,你会注意到它不会被随时调用。

    原因是这样的:

    vector&lt;Point2D*&gt; points; // Vector of Point2D*

    但是bool operator&lt; (Point2D a, Point2D b)是用来比较的。

    建议的修复:

    vector<Point2D> points;
    
    points.push_back(Point2D(my_x, my_y));
    

    相应地,只要适用。

    你也不能定义像

    这样的东西

    bool operator&lt;(const Point2D* a, const Point2D* b)

    因为这个:

    C++03 标准,§13.5 [over.oper] p6:

    操作符函数要么是非静态成员函数,要么是 是一个非成员函数,并且至少有一个类型为 类、对类的引用、枚举或对 枚举。

    【讨论】:

    • 该运算符将导致与他想要的完全不同的顺序。他似乎正在尝试按与原点的距离对点进行排序。
    猜你喜欢
    • 1970-01-01
    • 2012-02-22
    • 2011-10-22
    • 2019-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多