【问题标题】: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;会出现什么错误?

标签: c++ algorithm stl


【解决方案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. 如果没有对任一范围的排序要求(以及随机访问迭代器),复杂性会更高(取决于使用额外的结构/预排序)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-02
    • 1970-01-01
    • 2015-11-13
    • 1970-01-01
    • 2011-01-22
    • 2017-07-20
    • 1970-01-01
    • 2019-02-09
    相关资源
    最近更新 更多