为啥我们必须重载“<”运算符才能使用 is_permutation 并包含算法

Posted

技术标签:

【中文标题】为啥我们必须重载“<”运算符才能使用 is_permutation 并包含算法【英文标题】:why do we have to overload the '<' operator to use is_permutation and includes algorithm为什么我们必须重载“<”运算符才能使用 is_permutation 并包含算法 【发布时间】:2019-05-04 10:16:05 【问题描述】:

我有一个包含点向量的向量是一个具有 x 和 y 坐标的类。我基本上必须从我的向量中删除所有排列和子集。为此,我使用算法包括和 is_permutation

我已经重载了 '==' 运算符,我们需要它是有道理的。但是除非我重载'

这是我的点课:

class Point

private:    
    int x;
    int y;
public:
    Point()
        x=0;
        y=0;
    
    Point(int xx, int yy)
        x=xx;
        y=yy;
    

    double getSlope(Point p)
        if(this->x!=p.x && this->y!=p.y)
            return (double)(double(this->y-p.y)/double(this->x-p.x));
        else if(this->x==p.x)
            return INT_MAX;
        else
            return INT_MIN;
        
       
    void print()
        cout<<"(" <<x<<","<<y<<")";
    
    bool operator == (Point &p)
    if(this->x==p.x && this->y==p.y )
        return true;
    else
        return false;
    
    bool operator < (Point &p)
        cout<<"\nin the < operator\n";
    if(this->x < p.x && this->y < p.y )
        return true;
    else
        return false;
    
;

这是一个接收点的临时向量的函数 并将其与 vector> 进行比较以删除排列。 这些点是从文件中获取的,因此我们只在通过检查时才将其添加到向量中的点

bool check(PointVector temp, vector<PointVector> pointArrays )

    for(int i =0 ; i < pointArrays.size(); i++)
        if(is_permutation(pointArrays[i].begin(),pointArrays[i].end(),temp.begin()))
            return false;
        else if(includes(pointArrays[i].begin(),pointArrays[i].end(),temp.begin(),temp.end()))
            return false;
        else if(includes(temp.begin(),temp.end(),pointArrays[i].begin(),pointArrays[i].end()))
            pointArrays[i].swap(temp);
            return false;
        

    
    return true;

点向量是vector&lt;points&gt;; 的类型定义

【问题讨论】:

不重载&lt;会出现什么错误? 【参考方案1】:

这大约是std::includes,它对要排序的输入序列提出了要求(根据比较器 - operator&lt;)。

在这个前提条件下,算法可以用operator==(语义不是&lt;而不是&gt;)和相同的线性渐近复杂度来实现。1对于第一个长度为 n 的范围和长度为 m 的第二个范围,我们迭代第一个范围,每次将元素与第二个范围的当前元素进行比较。在匹配时,我们像往常一样将迭代器增加到两个范围。所以,这是 O(n+m) = O(n),因为 n false。问题是如果 n > m 并且结果应该是false,我们必须迭代整个第一个范围来查看(在检查第一个范围的 n - m + 1 个元素与第二个范围的第一个元素之前,我们无法决定)范围)。 n - m 越大越差。

但是使用operator&lt;,我们可以更快地做出决定(更确切地说,永远不会更晚),我们是否应该从算法中返回false,因为我们已经从第二个序列中读取了一个元素,该元素在下一个序列之前第一个序列。


示例:

1 是 2, ..., 106 的子范围吗?

         operator==: 106 - 1 次比较                       operator&lt;: 1 次比较

即使是operator&lt; 版本,在这个示例中仍然会受到影响:

106 是 1, ..., 106 - 1 的子范围吗?

         operator==: 106 - 1 次比较                        operator&lt;: 106 - 1 次比较

然后由程序员选择预期的迭代方向以产生更短的决策时间。

总体而言,处理有序序列的算法在顺序比较方面起作用,因为它们可以更深入地了解输入序列。


1. 如果没有对任一范围的排序要求(以及随机访问迭代器),复杂性会更高(取决于使用额外的结构/预排序)。

【讨论】:

以上是关于为啥我们必须重载“<”运算符才能使用 is_permutation 并包含算法的主要内容,如果未能解决你的问题,请参考以下文章

c++中重载输出操作符,为啥要返回引用

为啥我们在赋值运算符重载中使用引用返回而不是在加减运算中?

为啥我们在重载赋值中使用 return *this? [复制]

c++中为啥赋值运算符重载返回类型是引用

为啥我们需要在 express.js 服务器上使用代理才能获得 webpack 热重载服务器功能与 react-routing 相结合

为啥我们需要在 express.js 服务器上使用代理才能获得与 react-routing 相结合的 webpack 热重载服务器功能